Python 列出 OO 编程中的别名或全局变量。不同的结果,相同的过程
Python list aliasing or global variables in OO programming. Different result, same process
我知道 a+=b 和 a=a+b 并不总是给出相同的结果,这取决于它们引用的内容(如果我在这里错了请纠正我)。
我也知道 Python 中的列表别名问题。看这里:(Yet Another) List Aliasing Conundrum
下面的问题好像都不是这些,所以我不确定是什么问题。
我有以下程序。特别注意add_clouds()最后一行和add_hosts().[=最后一行5=]
在此处定义全局变量和类
global REQUESTS
global CLOUDS
REQUESTS = []
CLOUDS = []
class Cloud:
def __init__(self, ID, coordinate, Hosts):
self.ID = ID
self.coordinate = coordinate # coordinate should be a tuple
self.Hosts = Hosts # Hosts should be a list of Host objects
class Host:
def __init__(self, ID, Resources, Cloud):
self.ID = ID
self.Resources = Resources # coordinate should be a tuple
self.Cloud = Cloud # Cloud object (NOT the Cloud ID)
这部分生成云和主机
def add_cloud(ID,coordinate,Hosts=[]):
global CLOUDS
CLOUDS += [Cloud(ID, coordinate, Hosts)]
def add_host(Cloud_ID, Resources):
# search CLOUDS for Cloud_ID
Cloud = getCloud(Cloud_ID)
ID = len(Cloud.Hosts)+1
Cloud.Hosts += [Host(ID,Resources,Cloud)]
def getCloud(ID):
# returns cloud with ID provided
for cloud in CLOUDS:
if ID == cloud.ID:
return cloud
add_cloud(1,(10.7,13.5))
add_cloud(2,(1.8,3.0))
add_host(1,128)
shell 中的结果:
>>> CLOUDS
[<Cloud_Traversal.Cloud instance at 0x027336C0>, <Cloud_Traversal.Cloud instance at 0x02733DF0>]
>>> CLOUDS[1].Hosts
[<Cloud_Traversal.Host instance at 0x027334E0>]
>>> CLOUDS[0].Hosts
[<Cloud_Traversal.Host instance at 0x027334E0>]
>>>
你可以看到主机以某种方式添加到两个云中,即使我只明确地将它添加到一个云中(在 add_host(1,128) 行中) .
我已经尝试查看这是否是一个别名问题,但我认为我没有违反这里的任何规则。您知道可能是什么问题吗?
您在定义 (add_cloud
) 中使用了空列表语法 []
。那是不行的。看到这个答案:
看到这个 post:"Least Astonishment" and the Mutable Default Argument
当Python执行以下代码时:
def add_cloud(ID,coordinate,Hosts=[]):
global CLOUDS
CLOUDS += [Cloud(ID, coordinate, Hosts)]
它创建一个函数对象,并将在元组中指定的默认参数值存储在属性 func_defaults
下。参见:
>>> print add_cloud.func_defaults
([],)
所以基本上默认参数总是引用同一个列表。而且您的云也将全部保存指向同一个列表的指针,因此将主机添加到一个云将影响所有其他云,包括您将来可能创建的任何新云。
为防止这种情况,请改为执行以下操作:
def add_cloud(ID,coordinate,Hosts=None):
if Hosts is None:
Hosts = []
global CLOUDS
CLOUDS += [Cloud(ID, coordinate, Hosts)]
关于这个主题还有一个great effbot article。
问题在这里:
def add_cloud(ID,coordinate,Hosts=[]):
参数Hosts
的默认值是[]
,但是Python只计算一次次。因此,您第二次调用 add_cloud
时,Hosts
将不会再次分配给 []
。
这会导致您在创建对象时作为参数传递的列表
CLOUDS += [Cloud(ID, coordinate, Hosts)]
每次调用 add_cloud
时都是一样的。
你能做什么?
一件事是以下验证:
def add_cloud(ID, coordinate, Hosts = None):
if Hosts is None:
Hosts = []
...
注意事项:记得关注Python naming conventions.
我知道 a+=b 和 a=a+b 并不总是给出相同的结果,这取决于它们引用的内容(如果我在这里错了请纠正我)。 我也知道 Python 中的列表别名问题。看这里:(Yet Another) List Aliasing Conundrum
下面的问题好像都不是这些,所以我不确定是什么问题。
我有以下程序。特别注意add_clouds()最后一行和add_hosts().[=最后一行5=]
在此处定义全局变量和类
global REQUESTS
global CLOUDS
REQUESTS = []
CLOUDS = []
class Cloud:
def __init__(self, ID, coordinate, Hosts):
self.ID = ID
self.coordinate = coordinate # coordinate should be a tuple
self.Hosts = Hosts # Hosts should be a list of Host objects
class Host:
def __init__(self, ID, Resources, Cloud):
self.ID = ID
self.Resources = Resources # coordinate should be a tuple
self.Cloud = Cloud # Cloud object (NOT the Cloud ID)
这部分生成云和主机
def add_cloud(ID,coordinate,Hosts=[]):
global CLOUDS
CLOUDS += [Cloud(ID, coordinate, Hosts)]
def add_host(Cloud_ID, Resources):
# search CLOUDS for Cloud_ID
Cloud = getCloud(Cloud_ID)
ID = len(Cloud.Hosts)+1
Cloud.Hosts += [Host(ID,Resources,Cloud)]
def getCloud(ID):
# returns cloud with ID provided
for cloud in CLOUDS:
if ID == cloud.ID:
return cloud
add_cloud(1,(10.7,13.5))
add_cloud(2,(1.8,3.0))
add_host(1,128)
shell 中的结果:
>>> CLOUDS
[<Cloud_Traversal.Cloud instance at 0x027336C0>, <Cloud_Traversal.Cloud instance at 0x02733DF0>]
>>> CLOUDS[1].Hosts
[<Cloud_Traversal.Host instance at 0x027334E0>]
>>> CLOUDS[0].Hosts
[<Cloud_Traversal.Host instance at 0x027334E0>]
>>>
你可以看到主机以某种方式添加到两个云中,即使我只明确地将它添加到一个云中(在 add_host(1,128) 行中) .
我已经尝试查看这是否是一个别名问题,但我认为我没有违反这里的任何规则。您知道可能是什么问题吗?
您在定义 (add_cloud
) 中使用了空列表语法 []
。那是不行的。看到这个答案:
看到这个 post:"Least Astonishment" and the Mutable Default Argument
当Python执行以下代码时:
def add_cloud(ID,coordinate,Hosts=[]):
global CLOUDS
CLOUDS += [Cloud(ID, coordinate, Hosts)]
它创建一个函数对象,并将在元组中指定的默认参数值存储在属性 func_defaults
下。参见:
>>> print add_cloud.func_defaults
([],)
所以基本上默认参数总是引用同一个列表。而且您的云也将全部保存指向同一个列表的指针,因此将主机添加到一个云将影响所有其他云,包括您将来可能创建的任何新云。
为防止这种情况,请改为执行以下操作:
def add_cloud(ID,coordinate,Hosts=None):
if Hosts is None:
Hosts = []
global CLOUDS
CLOUDS += [Cloud(ID, coordinate, Hosts)]
关于这个主题还有一个great effbot article。
问题在这里:
def add_cloud(ID,coordinate,Hosts=[]):
参数Hosts
的默认值是[]
,但是Python只计算一次次。因此,您第二次调用 add_cloud
时,Hosts
将不会再次分配给 []
。
这会导致您在创建对象时作为参数传递的列表
CLOUDS += [Cloud(ID, coordinate, Hosts)]
每次调用 add_cloud
时都是一样的。
你能做什么?
一件事是以下验证:
def add_cloud(ID, coordinate, Hosts = None):
if Hosts is None:
Hosts = []
...
注意事项:记得关注Python naming conventions.