Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以设置Python对象的任何属性_Python_Class_Object_Properties - Fatal编程技术网

可以设置Python对象的任何属性

可以设置Python对象的任何属性,python,class,object,properties,Python,Class,Object,Properties,例如,这段代码是Python: a = object() a.b = 3 抛出属性错误:“对象”对象没有属性“b” 但是,这段代码: class c(object): pass a = c() a.b = 3 很好。为什么我可以分配属性b,而类x没有该属性?如何使我的类只定义属性?这是因为当你说a.b=3时,它会在a中创建一个表示b的变量。比如说, class a: pass print a.b 返回AttributeError:class a没有属性b 但是这个代码, class a:

例如,这段代码是Python:

a = object()
a.b = 3
抛出属性错误:“对象”对象没有属性“b”

但是,这段代码:

class c(object): pass
a = c()
a.b = 3

很好。为什么我可以分配属性b,而类x没有该属性?如何使我的类只定义属性?

这是因为当你说
a.b=3
时,它会在a中创建一个表示b的变量。比如说,

class a: pass
print a.b
返回
AttributeError:class a没有属性b

但是这个代码,

class a: pass
a.b = 3
print a.b

返回3,因为它将a中b的值设置为3。

Python通常允许您在任何对象上设置任何属性。这是一种特殊情况,
对象
类的行为不同。还有一些用C实现的模块,它们的作用类似


如果希望对象的行为类似于此,则可以定义一个
\uuuuSetAttr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(self、name、value)
方法,该方法显式执行
提升AttributeError()
如果试图设置一个不在“已批准列表”中的成员(请参见)

则可以像

class C(object):
    def __setattr__(self, name, value):
        allowed_attrs = ('a', 'b', 'c')
        if name not in allowed_attrs:
            # raise exception
            # or do something else
            pass
        self.__dict__[name] = value
当然,这只会阻止您设置a.b(点形式)之类的属性。您仍然可以使用
a.\uu dict\uuuu[b]
=value来设置属性。在这种情况下,您也应该重写
\uuu dict\uu
方法。

创建实例没有任何功能。因此,在基
对象
类型的实例上设置属性被明确禁用。必须将其子类化才能创建属性

提示:如果您想将一个简单对象用作存储属性的对象,可以使用
lambda
创建一个匿名函数。作为对象的函数也能够存储属性,因此这是完全合法的:

>>> a = lambda: None
>>> a.b = 3
>>> a.b 
3

对象
类型是用C编写的内置类,不允许向其添加属性。它已被明确编码,以防止它

要在自己的类中获得相同的行为,最简单的方法是使用
\uuuu\uu\uu
属性定义要支持的确切属性的列表。Python将仅为这些属性保留空间,而不允许任何其他属性

class c(object):
    __slots__ = "foo", "bar", "baz"

a = c()

a.foo = 3  # works
a.b   = 3  # AttributeError
当然,这种方法有一些警告:您不能对这些对象进行pickle处理,而期望每个对象都具有
\uuuu dict\uuu
属性的代码将被破坏。“更具Python风格”的方法是使用另一张海报所示的自定义
\uuuu setattr\uuuu()
。当然,有很多方法可以解决这个问题,而设置
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu插槽
(除了子类化和将属性添加到子类中之外)


一般来说,这并不是您实际需要在Python中执行的操作。如果您的类的用户希望在类的实例上存储一些额外的属性,那么没有理由不让它们存储,事实上,您可能有很多理由想这样做。

这并不能回答为什么他可以在第二种情况下执行
a.b=3
,但在第一种情况下不行。我没有,也不会,但是我不得不说,这并不能完全回答这个问题。
我如何才能使我的类只定义属性?
——应该指出的是,这只是没有充分理由的大量额外工作,可能会破坏一些有用的元编程,因此,除非你有充分的理由这样做,并且确切地知道你在做什么,否则应该避免这样做。这很好,我不知道有什么有趣的方法!我不知道
\uuuuuuuuuuuuuuuuuuuu
。然而,我在仔细阅读这种方法的注意事项时,无意中发现了。该线程中提到了一些好的警告。尤其是如果我们使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu!是的,这些都是很好的警告。一种更具python风格的方法可能是编写自己的
\uuuu setattr\uuuu()
来禁止未经批准的属性。当然,使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。