2011-08-09 21 views
1

在之前的文章中,我被告知我是用Python編寫的,就像在BASIC中編寫的那樣(我還沒有在Python中「思考」)。這可能是真實的,這就是我需要幫助的原因。這是說,我看過一本書有關Python至今(Python的的字節),我在網上買了兩本書(其中一個是與Python,我正在讀發明)和我做了很多的教程從該新波士頓。儘管如此,我的問題對你來說可能聽起來很新奇。將程序從FreeBASIC轉換爲Python:全局變量

在FreeBasic中,變量都是全球化的。在Python中,我必須將它們全局化爲我創建的每個新函數。這不太實際。那麼我期望做什麼? 「本地Python發言人」如何解決這個問題?下面你會發現一個我創建的小程序,我在函數內的所有變量中全局化。

#-*- coding: iso8859_1 -*- 

import random 

ca1 = 10 
ca2 = 10 
taco = 20 
pv1 = random.randint(1,10) 
pv2 = random.randint(1,10) 
cnt = 0 
pv1Dep = pv1 
pv2Dep = pv2 
ast = "*" * 7 
d20_1 = random.randint(1,20) 
d8_1 = random.randint(1,8) 
d20_2 = random.randint(1,20) 
d8_2 = random.randint(1,8) 

def intro(): 
    global ca1 
    global ca2 
    global taco 
    global pv1 
    global pv2 
    global cnt 
    global pv1Dep 
    global pv2Dep 
    global d20_1 
    global d8_1 
    global d20_2 
    global d8_2 


    print "Imaginez deux guerriers de D&D 2e édition qui se battent." 
    print 
    print "Guerrier 1: " + str(pv1) + " PV, épée longue (1-8 points de dégât), TACO de 20, CA de " + str(ca1) + "." 
    print "Guerrier 2: " + str(pv2) + " PV, épée longue (1-8 points de dégât), TACO de 20, CA de " + str(ca2) + "." 
    print 

def nouveauCombat(): 
    global ca1 
    global ca2 
    global taco 
    global pv1 
    global pv2 
    global cnt 
    global pv1Dep 
    global pv2Dep 
    global d20_1 
    global d8_1 
    global d20_2 
    global d8_2 

    print ast + "NOUVEAU COMBAT" + ast 
    print 
    while ((pv1 > 0) and (pv2 > 0)): 
     cnt = cnt + 1 
     print ast + "ROUND " + str(cnt) + ": INITIATIVE" + ast 
     print 
     calcInitiative() 
     print 
    print ast + "RESULTAT" + ast 
    print 
    resultat() 

def calcInitiative(): 
    global ca1 
    global ca2 
    global taco 
    global pv1 
    global pv2 
    global cnt 
    global pv1Dep 
    global pv2Dep 
    global d20_1 
    global d8_1 
    global d20_2 
    global d8_2 

    initiative1 = random.randint(1,10) 
    initiative2 = random.randint(1,10) 
    print "Le guerrier 1 fait son jet d'initiative." 
    print str(initiative1) + "!" 
    print 
    print "Le guerrier 2 fait son jet d'initiative." 
    print str(initiative2) + "!" 
    print 
    if initiative1 == initiative2: 
     print "Les deux guerriers attaquent au même moment." 
     print 
     print ast + "ROUND " + str(cnt) + ": ATTAQUE" + ast 
     print 
     attaque1() 
     print 
     attaque2() 
    elif initiative1 < initiative2: 
     print "Le guerrier 1 attaque en premier." 
     print 
     print ast + "ROUND " + str(cnt) + ": ATTAQUE" + ast 
     print 
     attaque1() 
     print 
     if pv2 > 0: 
      print 
      attaque2() 
    else: 
     print "Le guerrier 2 attaque en premier." 
     print 
     print ast + "ROUND " + str(cnt) + ": ATTAQUE" + ast 
     print 
     attaque2() 
     print 
     if pv1 > 0: 
      print 
      attaque2() 

def attaque1(): 
    global ca1 
    global ca2 
    global taco 
    global pv1 
    global pv2 
    global cnt 
    global pv1Dep 
    global pv2Dep 
    global d20_1 
    global d8_1 
    global d20_2 
    global d8_2 

    print "Le guerrier 1 fait son jet de toucher." 
    print str(d20_1) + "!" 
    if d20_1 >= ca2: 
     print "Touché!" 
     pv2 = pv2 - d8_1 
     print str(d8_1) + " points de dégât!" 
     print "Le guerrier 2 est à " + str(pv2) + "/" + str(pv2Dep) + " PV!" 
    else: 
     print "Raté!" 

def attaque2(): 
    global ca1 
    global ca2 
    global taco 
    global pv1 
    global pv2 
    global cnt 
    global pv1Dep 
    global pv2Dep 
    global d20_1 
    global d8_1 
    global d20_2 
    global d8_2 

    print "Le guerrier 2 fait son jet de toucher." 
    print str(d20_2) + "!" 
    if d20_2 >= ca1: 
     print "Touché!" 
     pv1 = pv1 - d8_2 
     print str(d8_2) + " points de dégât!" 
     print "Le guerrier 1 est à " + str(pv1) + "/" + str(pv1Dep) + " PV!" 
    else: 
     print "Raté!" 

def resultat(): 
    global ca1 
    global ca2 
    global taco 
    global pv1 
    global pv2 
    global cnt 
    global pv1Dep 
    global pv2Dep 
    global d20_1 
    global d8_1 
    global d20_2 
    global d8_2 

    print "Le combat prend fin au round " + str(cnt) + "." 
    print 

    if pv1 == pv1Dep: 
     print "Le guerrier 1 n'a pas la moindre égratignure." 
    elif pv1 > 0: 
     print "Le guerrier 1 est blessé." 
    else: 
     print "Le guerrier 1 est mort." 

    print "Il finit le combat avec " + str(pv1) + "/" +str (pv1Dep) + " PV." 
    print 

    if pv2 == pv2Dep: 
     print "Le guerrier 2 n'a pas la moindre égratignure." 
    elif pv2 > 0: 
     print "Le guerrier 2 est blessé." 
    else: 
     print "Le guerrier 2 est mort." 

    print "Il finit le combat avec " + str(pv2) + "/" +str (pv2Dep) + " PV." 
    print 

intro() 
nouveauCombat() 

回答

2

我重組你的程序向您展示的object oriented programming基礎。你需要了解類和對象。您還應該看看string formatting以正確的方式將字符串放在一起。

基本上,你創建兩個玩家對象,然後爲這兩個玩家創建一個戰鬥物體。然後,你打電話方法對戰對象爲了實際做戰鬥。 self類別是如何引用其本身的實例。任何好的Python教程都應該教會你所有這些東西。

唯一剩下的全局變量是一個常量,ast。全局常量偶爾可以。

#-*- coding: iso8859_1 -*- 
import random 
ast = "*" * 7 

class Player(object): 
    def __init__(self, num, ca): 
     self.ca = ca 
     self.num = num 
     self.pv = random.randint(1,10) 
     self.d20 = random.randint(1,20) 
     self.d8 = random.randint(1,8) 
     self.pvDep= self.pv 

class Combat(object): 
    def __init__(self, player1, player2): 
     self.player1 = player1 
     self.player2 = player2 
     self.cnt = 0 

    def intro(self): 
     print "Imaginez deux guerriers de D&D 2e édition qui se battent." 
     print 
     print "Guerrier 1: " + str(player1.pv) + " PV, épée longue (1-8 points de dégât), TACO de 20, CA de " + str(player1.ca) + "." 
     print "Guerrier 2: " + str(player2.pv) + " PV, épée longue (1-8 points de dégât), TACO de 20, CA de " + str(player2.ca) + "." 
     print 

    def nouveauCombat(self): 
     print ast + "NOUVEAU COMBAT" + ast 
     print 
     while ((self.player1.pv > 0) and (self.player2.pv > 0)): 
      self.cnt = self.cnt + 1 
      print ast + "ROUND " + str(self.cnt) + ": INITIATIVE" + ast 
      print 
      self.calcInitiative() 
      print 
     print ast + "RESULTAT" + ast 
     print 
     self.resultat() 

    def calcInitiative(self): 
     initiative1 = random.randint(1,10) 
     initiative2 = random.randint(1,10) 
     print "Le guerrier 1 fait son jet d'initiative." 
     print str(initiative1) + "!" 
     print 
     print "Le guerrier 2 fait son jet d'initiative." 
     print str(initiative2) + "!" 
     print 
     if initiative1 == initiative2: 
      print "Les deux guerriers attaquent au même moment." 
      print 
      print ast + "ROUND " + str(self.cnt) + ": ATTAQUE" + ast 
      print 
      self.attaque(self.player1, self.player2) 
      print 
      self.attaque(self.player2, self.player1) 
     elif initiative1 < initiative2: 
      print "Le guerrier 1 attaque en premier." 
      print 
      print ast + "ROUND " + str(self.cnt) + ": ATTAQUE" + ast 
      print 
      self.attaque(self.player1, self.player2) 
      print 
      if self.player2.pv > 0: 
       print 
       self.attaque(self.player2, self.player1) 
     else: 
      print "Le guerrier 2 attaque en premier." 
      print 
      print ast + "ROUND " + str(self.cnt) + ": ATTAQUE" + ast 
      print 
      self.attaque(self.player2, self.player1) 
      print 
      if self.player1.pv > 0: 
       print 
       self.attaque(self.player1, self.player2) 

    def attaque(self, player1, player2): 
     print "Le guerrier" + str(player1.num) + " fait son jet de toucher." 
     print str(player1.d20) + "!" 
     if player1.d20 >= player2.ca: 
      print "Touché!" 
      player2.pv = player2.pv - player1.d8 
      print str(player1.d8) + " points de dégât!" 
      print "Le guerrier 2 est à " + str(player2.pv) + "/" + str(player2.pvDep) + " PV!" 
     else: 
      print "Raté!" 

    def resultat(self): 
     print "Le combat prend fin au round " + str(self.cnt) + "." 
     print 

     if player1.pv == player1.pvDep: 
      print "Le guerrier 1 n'a pas la moindre égratignure." 
     elif player1.pv > 0: 
      print "Le guerrier 1 est blessé." 
     else: 
      print "Le guerrier 1 est mort." 

     print "Il finit le combat avec " + str(player1.pv) + "/" +str (player1.pvDep) + " PV." 
     print 

     if player2.pv == player2.pvDep: 
      print "Le guerrier 2 n'a pas la moindre égratignure." 
     elif player2.pv > 0: 
      print "Le guerrier 2 est blessé." 
     else: 
      print "Le guerrier 2 est mort." 

     print "Il finit le combat avec " + str(player2.pv) + "/" +str (player2.pvDep) + " PV." 
     print 


player1 = Player(1, 10) 
player2 = Player(2, 10) 
combat = Combat(player1, player2) 
combat.intro() 
combat.nouveauCombat() 
+0

謝謝!這很好,讓你看起來像這樣! – erlang

3

除非打算指定名稱,否則不需要聲明名稱爲全局名稱。

a = 1 
b = 2 
def foo(): 
    global b 
    print a # prints 1 
    b = 3 
foo() 
print b # prints 3 
+0

這並沒有真正回答他的問題 - 他應該怎麼做而不是使用全局變量? – agf

1

默認情況下,全局變量被普遍認爲是一個設計缺陷。如果你想寫「Pythonic」代碼,你應該努力爭取儘可能少的全局狀態。

+0

是的,但他是怎麼做到的?他在 – agf

+0

之前沒有做過這種編程。您應該傳遞函數實際需要的任何數據作爲參數。回顧一下這個例子,創建一個類可能是最乾淨的,但假設你不想立刻將太多新想法投入混合,顯式參數是一個完全可以接受的選項。 –

2

在Python中,在許多現代語言,大量使用全局變量被認爲是一個反模式。原因很多:

  • 它妨礙函數重入,這對高效的多線程代碼很重要。
  • 它使單元測試更難,這是對中有助於大型項目
  • 它使模塊更加相互依賴,這使得它難以追查的問題和解決這些問題一旦被發現。

你應該endevor到每個功能所需要的數據:

def foo(): 
    bar = 10 
    baz(bar) 

def baz(bar): 
    print bar 

如果你需要從一個功能捕捉狀態到下一個,你可以換行到一類。

class quux(object): 
    def __init__(self): 
     self.a = 1 
     self.b = "two" 

def foo(): 
    bar = quux() 
    baz(bar) 
    print bar.a, bar.b 

def baz(bar): 
    bar.a = len(bar.b) 

總之,你幾乎從來沒有需要全局,但在很多情況下,你需要有東西是全球。