Python 类成员 [英] Python Class Members

查看:28
本文介绍了Python 类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚学习 Python,我有 C 背景,所以如果我对两者有任何混淆/混淆,请告诉我.

假设我有以下课程:

类节点(对象):def __init__(self, element):self.element = 元素self.left = self.right = 无@类方法def树(cls,元素,左,右):节点 = cls(元素)node.left = 左node.right = 正确返回节点

这是一个名为 Node 的类,它重载了构造函数,以便在需要时能够处理不同的参数.

仅在 __init__ 中定义 self.element(如上所示)与执行以下操作有什么区别:

类节点(对象):元素,左,右 = 无def __init__(self, element):self.element = 元素self.left = self.right = 无

__init__ 中的self.element 不是和类的element 变量定义的一样吗?这不会将 elementNone 覆盖到传递给 __init__element 值吗?

解决方案

一个是类属性,另一个是实例属性.它们是不同的,但它们以某种方式彼此密切相关,使它们有时看起来相同.

这与python查找属性的方式有关.有层次感.在简单的情况下,它可能如下所示:

 实例 ->子类 ->超类 ->对象(内置类型)

当你像这样在 instance 上寻找一个属性时......

`instance.val`

...实际发生的是首先,Python 在实例本身中查找 val.然后,如果它没有找到 val,它会在它的类中查找,Subclass.然后,如果在那里没有找到val,它会在SubclassSuperclass 的父级中查找.这意味着当你这样做时......

<预><代码>>>>类 Foo():foovar = 10def __init__(self, val):self.selfvar = val

...Foo share foovar 的所有实例,但都有自己独特的 selfvar .下面是一个简单、具体的示例,说明其工作原理:

<预><代码>>>>f = Foo(5)>>>福瓦尔10>>>foovar10

如果我们不接触foovar,对于fFoo 来说都是一样的.但是如果我们改变 f.foovar...

<预><代码>>>>f.foovar = 5>>>福瓦尔5>>>foovar10

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

<预><代码>>>>foo.foovar = 7>>>福瓦尔5

但它确实影响了一个新的 foo 实例:

<预><代码>>>>Foo(5).foovar7

还要记住,可变对象增加了另一层间接性(正如 mgilson 提醒我的那样).此处,f.foovarFoo.foovar 指代相同的对象,因此当您更改对象时,更改会沿层次结构向上传播:

<预><代码>>>>Foo.foovar = [1]>>>f = Foo(5)>>>f.foovar[0] = 99>>>foovar[99]

I am just learning Python and I come from a C background so please let me know if I have any confusion / mix up between both.

Assume I have the following class:

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

This is a class named Node, that overloads the constructor, to be able to handle different arguments if needed.

What is the difference between defining self.element in __init__ only (as shown above) as opposed to doing the following:

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

Isn't self.element in __init__ the same as the class's element variable defined? Wouldn't that just overwrite element from None to the element value passed into __init__?

解决方案

One is a class attribute, while the other is an instance attribute. They are different, but they are closely related to one another in ways that make them look the same at times.

It has to do with the way python looks up attributes. There's a hierarchy. In simple cases it might look like this:

instance -> Subclass -> Superclass -> object (built-in type)

When you look for an attribute on instance like this...

`instance.val`

...what actually happens is that first, Python looks for val in the instance itself. Then, if it doesn't find val, it looks in its class, Subclass. Then, if it doesn't find val there, it looks in the parent of Subclass, Superclass. This means that when you do this...

>>> class Foo():
    foovar = 10  
    def __init__(self, val):
        self.selfvar = val

...all instances of Foo share foovar, but have their own distinct selfvars. Here's a simple, concrete example of how that works:

>>> f = Foo(5)
>>> f.foovar
10
>>> Foo.foovar
10

If we don't touch foovar, it's the same for both f and Foo. But if we change f.foovar...

>>> f.foovar = 5
>>> f.foovar
5
>>> Foo.foovar
10

...we add an instance attribute that effectively masks the value of Foo.foovar. Now if we change Foo.foovar directly, it doesn't affect our foo instance:

>>> Foo.foovar = 7
>>> f.foovar
5

But it does affect a new foo instance:

>>> Foo(5).foovar
7

Also keep in mind that mutable objects add another layer of indirection (as mgilson reminded me). Here, f.foovar refers to the same object as Foo.foovar, so when you alter the object, the changes are propagated up the hierarchy:

>>> Foo.foovar = [1]
>>> f = Foo(5)
>>> f.foovar[0] = 99
>>> Foo.foovar
[99]

这篇关于Python 类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆