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

发布于 2024-11-04 10:36:12 字数 282 浏览 0 评论 0原文

例如,这段代码是Python:

a = object()
a.b = 3

throws AttributeError: 'object' object has no attribute 'b'

但是,这段代码:

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

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

For example, this code is Python:

a = object()
a.b = 3

throws AttributeError: 'object' object has no attribute 'b'

But, this piece of code:

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

is just fine. Why can I assign property b, when class x does not have that property? How can I make my classes have only properties defined?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

薄凉少年不暖心 2024-11-11 10:36:12

object 类型是用 C 编写的内置类,不允许您向其添加属性。它已被明确编码以防止这种情况发生。

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

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

a = c()

a.foo = 3  # works
a.b   = 3  # AttributeError

当然,这种方法有一些注意事项:您无法腌制此类对象,并且期望每个对象都具有 __dict__ 属性的代码将会中断。一种“更Pythonic”的方法是使用自定义的__setattr__(),如另一张海报所示。当然,有很多方法可以解决这个问题,并且没有办法可以设置 __slots__ (除了子类化和将属性添加到子类之外)。

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

The object type is a built-in class written in C and doesn't let you add attributes to it. It has been expressly coded to prevent it.

The easiest way to get the same behavior in your own classes is to use the __slots__ attribute to define a list of the exact attributes you want to support. Python will reserve space for just those attributes and not allow any others.

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

a = c()

a.foo = 3  # works
a.b   = 3  # AttributeError

Of course, there are some caveats with this approach: you can't pickle such objects, and code that expects every object to have a __dict__ attribute will break. A "more Pythonic" way would be to use a custom __setattr__() as shown by another poster. Of course there are plenty of ways around that, and no way around setting __slots__ (aside from subclassing and adding your attributes to the subclass).

In general, this is not something you should actually want to do in Python. If the user of your class wants to store some extra attributes on instances of the class, there's no reason not to let them, and in fact a lot of reasons why you might want to.

紫罗兰の梦幻 2024-11-11 10:36:12

您可以像这样重写 __setattr__ 魔术方法的行为。

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

当然,这只会阻止您设置像 ab(点形式)这样的属性。您仍然可以使用 a.__dict__[b] = value 设置属性。在这种情况下,您也应该重写 __dict__ 方法。

You can override the behavior of the __setattr__ magic method like so.

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

Of course, this will only prevent you from setting attributes like a.b (the dot form). You can still set the attributes using a.__dict__[b] = value. In that case, you should override the __dict__ method too.

埋情葬爱 2024-11-11 10:36:12

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

如果您希望您的对象表现得像这样,您可以定义一个__setattr__(self, name, value)方法来显式执行raise AttributeError() code> 如果您尝试设置不在“批准列表”上的成员(请参阅 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/389916)

Python generally allows you to set any attribute on any object. This is a special case where the object class acts differently. There are also some modules implemented in C that act similarly.

If you want your object to behave like this, you can define a __setattr__(self, name, value) method that explicitly does a raise AttributeError() if you try to set a member that's not on the "approved list" (see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/389916)

傲性难收 2024-11-11 10:36:12

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

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

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

Creating an object instance has no features. Therefore setting attributes on an instance of a the base object type is expressly disabled. You must subclass it to be able to create attributes.

Hint: If you want a simple object to use as something on which to store properties, you can do so by creating an anonymous function with lambda. Functions, being objects, are able to store attributes as well, so this is perfectly legit:

>>> a = lambda: None
>>> a.b = 3
>>> a.b 
3
合约呢 2024-11-11 10:36:12

发生这种情况是因为当您说 ab = 3 时,它会在 a 中创建一个代表 b 的变量。例如,

class a: pass
print a.b

返回 AttributeError: class a has no attribute b

但是此代码

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

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

This happens because when you say a.b = 3, it creates a variable in a that represents b. For example,

class a: pass
print a.b

returns AttributeError: class a has no attribute b

However this code,

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

returns 3 as it sets the value of b in a, to 3.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文