向Python对象添加新属性?

时间:2014-04-04 17:44:05

标签: python

从OOPS背景来看,下面的link

代码看起来很奇怪
def f():
    f.beencalled = True
    return 0

我的问题:

1) 从上面的代码, f是指向f的对象class 'function'的引用变量吗?

2) 我们向对象beencalled添加了一个新属性f,因此现在'function'类没有定义此属性beencalled,我们说对象f是一个class 'function'的对象?它有意义吗?

3 个答案:

答案 0 :(得分:5)

1)是的:

>>> def f():
        print(type(f))

>>> <class 'function'>

2)function类没有新属性,但对象f没有。向对象添加属性或从对象添加属性不会影响该类的其他对象具有哪些属性:

>>> class A: pass
>>> a = A()
>>> a.var = 7
>>> b = A()
>>> b.var
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
    b.newvar
AttributeError: 'A' object has no attribute 'var'

python中的类比Java或C ++中的类更灵活。对象可以具有未在其类中定义的属性,甚至缺少在其类中定义的属性!看看这个:

>>> class A:
def __init__(self, a):
    self.var = a


>>> obj = A(7)
>>> del obj.var #deletes the var attribute from obj, does not change the A class
>>> obj.var
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    obj.var
AttributeError: 'A' object has no attribute 'var'

>>> obj2 = A(6)
>>> obj2.var #obj2 is a new object, so the fact we deleted var from obj doesn't affect it
6 

编辑:经过一些搜索,我找到了为什么选择这种行为的解释(source):

  

为了实现用户定义的对象,我选择了最简单的方法   设计;一种方案,其中对象由一种新的表示   内置对象,存储指向“类”的类引用   对象“由同一个类的所有实例共享,以及字典,   被称为“实例字典”,其中包含实例   变量

     

在此实现中,实例字典将包含   每个单独对象的实例变量,而类对象   将包含在同一个类的所有实例之间共享的东西 - 在   特别是方法。在实现类对象时,我再次选择了   最简单的设计;类的方法集存储在   一个字典,其键是方法名称。这个,我称之为班级   字典。为了支持继承,类对象将另外   存储对与基础对应的类对象的引用   类。当时,我对课程相当天真,但我知道   关于多重继承,最近已添加到C ++中。一世   我决定只要我支持继承,我就可以   很好地支持一个简单的多重继承版本。从而,   每个类对象都可以有一个或多个基类。

     

在此实现中,使用的基础机制   对象实际上非常简单。每当做出改变时   实例或类变量,这些变化只是反映在   基础字典对象。例如,设置实例   实例上的变量更新其本地实例字典。   同样,当查找一个实例变量的值时   对象,只需检查其实例字典是否存在   那个变量。如果在那里找不到变量,事情就变成了   更有趣。在这种情况下,查找是在   类字典然后在每个类的字典中   基类。

答案 1 :(得分:2)

稍微不同的是,您可以更改自定义类的此行为。

class FooBar(object):
    __slots__ = ["foo","bar","baz"]
    # if you don't define __slots__, you can add attr to the object as needed
    # if you do, the object can only contain those attributes.
    def __init__(self,foo=None,bar=None,baz=None):
        self.foo = foo
        self.bar = bar
        self.baz = baz
    def __str__(self):
        return "I'm a FooBar with id {0} with foo: {1.foo}, bar: {1.bar}, baz: {1.baz}".format(id(self),self)

>>> a = FooBar("a","B","CCC")
>>> print(a)
I'm a FooBar with id 47260256 with foo: a, bar: B, baz: CCC
>>> a.spam = "eggs"
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    a.spam = "eggs"
AttributeError: 'FooBar' object has no attribute 'spam'

或者,没有定义__slots__

class BooFar(object):
    def __str__(self):
        return "I'm a BooFar with the following attributes:\n{}".format(self.__dict__)

>>> b = BooFar()
>>> print(b)
I'm a BooFar with the following attributes:
{}
>>> b.spam = "eggs"
>>> print(b)
I'm a BooFar with the following attributes:
{'spam': 'eggs'}

答案 2 :(得分:1)

仅在f()的实例中

types.FunctionType,实例可以拥有自己的属性。

向实例添加属性不会影响其类,除非您重写了该类的__setattr__方法并在那里做了一些邪恶的事情。

>>> import types
>>> def func(): pass
>>> isinstance(func, types.FunctionType)
True