我想要一个类,能够更改对象值,并使其流到类中创建的方法和对象。在下面的例子中,我试图让新值3
通过,但我一直得到原始值2
。我做错了吗?
class fun:
g=2
def a(c=g):
return c
z=g
fun.g = 3
fun.a()
fun.z
我已经搜索了__init__
函数,但我看不出它们在这里有什么帮助。我尝试创建了一个新的类,使其与fun
类相同。这也没用。
正如其他人所提到的,我只想指出,在创建类的过程中,def a(c=g):
和g
已被2替换。
所以之后
fun.g = 3
print(fun.__dict__)
mappingproxy({'__module__': '__main__',
'g': 3,
'a': <function __main__.fun.a(c=2)>,
'z': 2,
'__dict__': <attribute '__dict__' of 'fun' objects>,
'__weakref__': <attribute '__weakref__' of 'fun' objects>,
'__doc__': None})
正如你所看到的'a': <function __main__.fun.a(c=2)>,
在python中,当声明方法或函数时,方法和函数会计算并存储其默认值。
您可以通过在运行时在方法内部进行计算来推迟计算:
class fun:
g=2
def a(c=None): # None is used here as a sentinal value
if c is None:
c=fun.g
return c
z=g
问题是函数的参数是在编译时而不是运行时求值的!因为在编译时,g
的值是2,而在函数中,您返回的值总是2。
作为一个要点,您在类本身上调用a()
函数,所以它的第一个参数不会用对实例的引用来填充。当您尝试从该类的实例调用故事时,故事会发生变化。
为了进行演示,请查看以下内容:
from datetime import datetime
from time import sleep
class C:
def fn(self, date=datetime.now()):
return date
obj = C()
print(obj.fn())
sleep(2)
print(obj.fn())
它们都有相同的价值。
解决方案是将默认值g
设置为None,然后在函数内部检查该值是否通过:
from datetime import datetime
from time import sleep
class C:
def fn(self, date=None):
if date:
return date
return datetime.now()
obj = C()
print(obj.fn())
sleep(2)
print(obj.fn())
不太清楚重新初始化是什么意思,__init__
只在创建时发生。如果您创建了一个新的fun
对象,它将以相同的方式使用相同的值进行初始化。
$ cat fun.py
class fun(object):
def __init__(self):
self.g = 2
def a(self, c=None):
if c is None:
c = self.g
return c
first = fun()
second = fun()
first.g = 3
print(first.g)
print(first.a())
print(second.g)
print(second.a())
$ python3 fun.py
3
3
2
2