在 Python 中,为什么不为所有导入文件声明变量到全局命名空间

In Python why aren't variables declared to global namspace for all imported files

在 C 和 PHP 中,如果我在文件中声明了一些变量然后包含它(在 PHP 中,它是已编译二进制文件的一部分)。它只是工作。为什么这在 python.

中不起作用

这是我在 PHP 中可以做的事情。

文件a.php

$a=1;
$b=2;

文件b.php

function add(){
   global $a,$b;
   return $a+$b;
}

文件c.php

require('a.php')
require('b.php')
echo add().PHP_EOL;

你回来了 3.

但是在 python 中,如果我做类似的事情,它会说该变量未定义。 在 data.py 中,我创建了以下 object/class。它不是任何函数的一部分,此处的缩进反映了与文件本身相同的 level/scope。

player=Player()

在textadventure.py中我有以下代码。

from data import *
from lib import *

在lib.py我有

def check_input(usr_input):
    inputs=usr_input.split(' ')
    verb=inputs[0]
    global player
    if len(inputs) >= 2:
        obj=inputs[1]
    else:
        obj=None

    if verb in verbs:
        if verb == 'move':
            player.location.move(obj)
        elif verb == 'look':
            look(obj)
    else:
        print('not valid')

def look(obj):
    global player
    current_room=player.location
    if obj is None:
        print(current_room.desc)
    else:
        if obj in current_room.items:
            print(current_room.items[obj].desc)
        elif obj in current_room.mobs:
            print(current_room.mobs[obj].desc)

然后我收到以下错误。

Traceback (most recent call last):
  File "text_adventure.py", line 84, in <module>
    main_loop()
  File "text_adventure.py", line 81, in main_loop
    check_input(usr_input)
  File "/home/macarthur/misc_proj/python_projects/text_adventure/lib.py", line 23, in check_input
    look(obj)
  File "/home/macarthur/misc_proj/python_projects/text_adventure/lib.py", line 48, in look
    current_room=player.location
NameError: name 'player' is not defined

所以我的问题是为什么这行不通。不要告诉我我必须 将每个文件导入 到每个其他文件以确保它实际上是全局命名空间的一部分。

data.py

from templates import *

letter=Item()
letter.desc="It's a letter you found in the mailbox."
letter.interact="The letters have faded but you can make out a single sentence 'Those in the dark fear the light.'"
mailbox=Mailbox()
mailbox.desc='It is a mailbox with the flag up and the front closed'
mailbox.action='interact'
mailbox.contains=letter
starter=Room("You are in a room with four exits 3[1m north east south west3[0m. There is a single mailbox before you.",mailbox,None)
letter.location=starter._id
mailbox.in_room=0
north=Room("You are in a room with a single source of light. A 3[1m flashlight.3[0m")
west=Room("You are in a wet room. There is a 3[1mfish3[0m flopping on the ground before you.")
east=Room("You are in an empty room. You can see nothing else")
south=Room("You are in a dark room. There is nothing that can be seen.")
starter.add_moves({'n':north,'e':east,'s':south,'w':west})
west.add_moves({'e':starter})
east.add_moves({'w':starter})
south.add_moves({'n':starter})

player=Player()
inventory=Inventory()

templates.py

class Item:
    _id=0
    desc=''
    interaction=''
    location=None
    def __init__(self,desc=desc,interact=interaction,location=location):
        self.desc=desc
        self.interaction=interact
        self.location=location
        self._id=Item._id
        Item._id+=1
    def get_item(self,player):
        move_location(self,-1)
        print("You have grabbed {} and put it into your 3[1minventory".format(self.desc))

    def move_location(self,location):
        self.location=location

class Weapon(Item):
    damage=0
    desc='It is a weapon'
    def __init__(self,damage=damage,desc=desc):
        self.damage=damage
        self.desc=desc


class World():
    rooms={}
    def __init__(self):
        pass
    def add_room(self,room):
        self.rooms[(room.x,room.y)]=room

class Mailbox(Item):
    contains='letter'
    def __init__(self,contains=contains):
        Item.__init__(self)
        self.contains=contains

class Player:
    x=0
    y=0
    location=None
    weapon=None
    dead=False
    hp=10
    def __init__(self):
        self.x=0
        self.y=0
        self.weapon=None
        self.dead=False
        self.location=None
        self.hp=10

    def damaged(amount):
        self.hp=self.hp-amount

class Inventory(Player):
    items={}
    def __init__(self,items=items):
        self.items=items

    def add(self,item):
        self.items.append(item)

    def show(self):
        for item in self.items:
            print(item._id.desc)

    def use(self,item):
        if item in items:
            print(item.interaction)
        else:
            print("You don't have that item")

class Room:
    desc="You're in a room"
    items=None
    mobs=None
    x=0
    y=0
    _id=0
    exits={}
    def __init__(self,desc=desc,items=items,mobs=mobs,x=x,y=y,exits=exits):
        self.exits=exits
        self.desc=desc
        self.items=items
        self.mobs=mobs
        self.x=x
        self.y=y
        self._id=Room._id
        Room._id+=1

    def add_moves(self,moves=exits):
        self.exits.update(moves)

    def move(self,movement,player):
        selected_move=self.exits.get(movement,None)
        if  selected_move:
            player.location=selected_move
        else:
            return None


class Mob:
    _id = 0
    desc="You can't discern anything about it."
    interact="It just looks at you."
    room=None
    alive=True
    name='None'
    hp=5
    def __init__(self,desc=desc,interact=interact,alive=alive,name=name,hp=hp):
        self.name=name
        self.desc=desc
        self.interact=interact
        self._id=Mob.id
        Mob._id+=1
        self.alive=alive
        self.hp=hp

class Grue(Mob):
    def __init__(self):
        super().__init__(desc='A giant grue stands before you',interact='You were eaten by a grue',name='Grue',hp=10)

根据@JohnGordon 的说法,任何模块(脚本)都需要了解在另一个模块(或脚本)中声明的 variables/objects。您必须导入它,以便它知道它。全局命名空间不像 PHP 或其他语言那样真正是全局的。

很像不能在条件 python 内分配变量似乎是在强制 "best practices"。