Executable statements in the header part of a Python class
我试图创建一个类,其中包含从几个文件中读取的各种数据。通常的方法可能是定义一个构造函数(
1 2 3 4 5 6 7 8 9 10 11 12 13 | from SomeOtherMod import reader # some data reader class Myclass: def __init__( self ): self.N = reader.readN() self.data = reader.readdata() self.foo = self.data.foo() self.bar = self.data.bar() ... # more data to read and associated properties follow def othefunc( self ): ... # use self.N, self.data, ... |
但似乎我也可以在类的头部分编写相同的东西,而不使用
1 2 3 4 5 6 7 8 9 10 | class Myclass: N = reader.readN() data = reader.readdata() foo = data.foo() bar = data.bar() ... def otherfunc( self ): ... |
这看起来比第一个代码更简洁。所以我想知道第二个代码是否是定义Python类的各种字段的有效方法?这样做被认为是不好的做法,还是第一种方法和第二种方法有什么区别?我会感谢任何建议,因为我对Python还是个新手。多谢!
这两种方法有重要的区别。在某些用例中,您可以用任何一种方法来实现,但它们绝对不是等价的。
对于第一个方法,在实例化类的实例之前,不会执行
第二种方法是在解释器第一次到达代码时执行类定义块内的语句。这可能在程序的开头(或附近),并且在导入包含类定义的模块时发生。这可能,也可能不适用于您的申请。
另外,请阅读juanpa.arrivilaga在注释中提供的链接,或者这个链接:为什么属性引用在Python继承中的作用是这样的?
是的-它们是非常不同的-当您在一个方法中分配给
在某些情况下,但并非总是如此,你可能会完全想要。您必须记住的是,如果yu更改了一个类属性,那么它将立即对该类的所有实例进行更改。
当然,python处理属性检索和赋值的方式有一种自然的表现,这使得类体中的赋值非常方便。如果有一个值应该是类的所有实例的默认值(例如,员工支出),但该值应该在对象生命周期的某个时间点进行自定义,则这是自然发生的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Employee: payout = 100 e1 = Employee() e2 = Employee() print(e1.payout, e2.payout) # Payout is read from the class as it does not exist in any instance # Python prints 100, 100 e1.payout = 120 # Now, an"payout" attribute is created in the"e1" instance print(e1.payout, e2.payout) # shows 120, 100 # And the outpt of the following lines will make # really clear what is going on: print(e1.__class__.__dict__, e2.__class__.__dict__) # shows"{'payout': 100, ...}, {'payout': 100, ...} print(e1.__dict__, e2.__dict__) # shows"{'payout': 120}, {} |
在第一种方法中,n、data、foo和bar是myclass实例的简单成员。每个MyClass对象都有自己的对象,更改一个对象对其他实例没有影响:
1 2 3 4 5 6 7 8 | class X(): def __init__(self): self.x = [] a = X() b = X() a.x.append(1) a.x != b.x |
在第二种方法中,它们是类的成员。您仍然可以通过实例访问它们,但它们将由所有实例共享。
1 2 3 4 5 6 7 | class X(): x = [] a = X() b = X() a.x.append(1) a.x == b.x == [1] |
两者都是有效的代码,但它们有不同的用途