Python类成员

9 浏览
0 Comments

Python类成员

我正在学习Python,之前有C的背景,如果我在两者之间有任何混淆/混合,请告诉我。

假设我有以下类:

class Node(object):
    def __init__(self, element):
        self.element = element
        self.left = self.right = None
    @classmethod
    def tree(cls, element, left, right):
        node = cls(element)
        node.left = left
        node.right = right
        return node

这是一个名为`Node`的类,它重载了构造函数,以便能够处理不同的参数(如果需要的话)。

在上述代码中,仅在`__init__`中定义`self.element`和下面这样做之间有什么区别:

class Node(object):
    element, left, right = None
    def __init__(self, element):
        self.element = element
        self.left = self.right = None

在`__init__`中的`self.element`和类定义的`element`变量不是相同的吗?这不只是将`element`从`None`覆盖为传递给`__init__`的`element`值吗?

0
0 Comments

Python中的类成员问题是由于构造函数(即__init__方法)中的self.element是一个实例变量(如果一个节点对象修改它的值,它只会对该对象生效),而第二个版本中的self.element是一个类变量(因此,如果一个节点对象修改它的值,它将对所有节点对象生效)。

在C++中,类成员变量的类比是非静态成员变量与静态成员变量。

解决这个问题的方法是将self.element声明为类变量,而不是实例变量。这可以通过将其放在类的__init__方法外部来实现,或者在构造函数内使用ClassName.element来引用它。

下面是解决这个问题的示例代码:

class Node:
    element = None
    
    def __init__(self, element):
        self.element = element

通过将element放在类的外部,它成为了一个类变量,而不是实例变量。这样,无论节点对象如何修改它的值,它都会对所有节点对象生效。

0
0 Comments

在Python中,可以同时拥有相同名称的类变量和实例变量。它们在内存中是分开存储的,并且访问方式也有所不同。

在你的代码中:

class Node(object):
    element, left, right = None
    def __init__(self, element):
        self.element = element
        self.left = self.right = None

第一组变量(在`__init__`函数之外)被称为类变量。可以通过`Node.element`等方式访问这些变量。它们相当于C++中的静态成员变量,它们被所有类的实例共享。

第二组变量(在`__init__`函数之内)被称为实例变量。可以通过`self`对象访问,例如`self.element`,或者在类外部通过实例名称访问,例如`myNode.element`。

重要的是要注意,如果要在成员函数中访问这两者中的任何一个,必须使用`self.variable`或`Node.variable`的形式。如果只访问`variable`,则会尝试访问一个名为`variable`的局部变量。

0
0 Comments

Python类成员(Python Class Members)之间的区别在于一个是类属性,而另一个是实例属性。尽管它们在某些情况下看起来相似,但它们实际上是有密切关联的。

这与Python查找属性的方式有关。有一个层次结构。在简单的情况下,它可能是这样的:

实例(instance) -> 子类(Subclass) -> 父类(Superclass) -> 对象(object,内置类型)

当你像这样在实例上查找属性时...

instance.val

...实际上发生的是,首先Python会在实例本身中查找val。然后,如果它在实例中找不到val,它会在其类Subclass中查找。然后,如果它在Subclass中找不到val,它会在Subclass的父类Superclass中查找。

这意味着当你这样做...

class Foo():

foovar = 10

def __init__(self, val):

self.selfvar = val

...Foo的所有实例共享foovar,但它们各自拥有自己的selfvar。以下是一个简单的具体示例:

f = Foo(5)

f.foovar

10

Foo.foovar

10

如果我们不修改foovar,它对f和Foo来说是相同的。但是如果我们更改f.foovar...

f.foovar = 5

f.foovar

5

Foo.foovar

10

...我们添加了一个实例属性,它有效地屏蔽了Foo.foovar的值。现在,如果我们直接更改Foo.foovar,它不会影响我们的foo实例:

Foo.foovar = 7

f.foovar

5

但是它会影响一个新的foo实例:

Foo(5).foovar

7

还要记住,可变对象会添加另一层间接性。在这里,f.foovar引用的是与Foo.foovar相同的对象,因此当你修改对象时,更改会向上传播到层次结构的上层:

Foo.foovar = [1]

f = Foo(5)

f.foovar[0] = 99

Foo.foovar

[99]

很棒的答案!在Foo.foovar是一个可变对象(如列表)的情况下,这些情况甚至会变得更有趣。

0