python、__slots__ 和“属性是只读的”
我想在 python 中创建一个具有一些属性的对象,并且我想防止自己意外使用错误的属性名称。 代码如下:
class MyClass( object ) :
m = None # my attribute
__slots__ = ( "m" ) # ensure that object has no _m etc
a = MyClass() # create one
a.m = "?" # here is a PROBLEM
但是运行这个简单的代码后,我得到一个非常奇怪的错误:
Traceback (most recent call last):
File "test.py", line 8, in <module>
a.m = "?"
AttributeError: 'test' object attribute 'm' is read-only
有没有聪明的程序员可以抽出一点时间来启发我有关“只读”错误的信息?
I want to create an object in python that has a few attributes and I want to protect myself from accidentally using the wrong attribute name. The code is as follows:
class MyClass( object ) :
m = None # my attribute
__slots__ = ( "m" ) # ensure that object has no _m etc
a = MyClass() # create one
a.m = "?" # here is a PROBLEM
But after running this simple code, I get a very strange error:
Traceback (most recent call last):
File "test.py", line 8, in <module>
a.m = "?"
AttributeError: 'test' object attribute 'm' is read-only
Is there any wise programmer who can spare a bit of their time and enlighten me about "read-only" errors?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当您使用 __slots__ 声明实例变量时,Python 会创建一个 描述符对象< /a> 作为同名的类变量。 在您的情况下,此描述符将被您在以下行中定义的类变量
m
覆盖:以下是您需要执行的操作:不要定义名为
m
的类变量code>,并在__init__
方法中初始化实例变量m
。作为旁注,具有单个元素的元组在元素后面需要一个逗号。 两者都可以在您的代码中工作,因为
__slots__
接受单个字符串或可迭代/字符串序列。 一般来说,要定义包含元素1
的元组,请使用(1,)
或1,
而不是(1)< /代码>。
When you declare instance variables using
__slots__
, Python creates a descriptor object as a class variable with the same name. In your case, this descriptor is overwritten by the class variablem
that you are defining at the following line:Here is what you need to do: Do not define a class variable called
m
, and initialize the instance variablem
in the__init__
method.As a side note, tuples with single elements need a comma after the element. Both work in your code because
__slots__
accepts a single string or an iterable/sequence of strings. In general, to define a tuple containing the element1
, use(1,)
or1,
and not(1)
.您完全滥用了
__slots__
。 它阻止为实例创建__dict__
。 仅当您遇到许多小对象的内存问题时,这才有意义,因为摆脱__dict__
可以减少占用空间。 这是一项硬核优化,在 99.9% 的情况下都不需要。如果您需要您所描述的那种安全性,那么 Python 确实是错误的语言。 最好使用像 Java 这样严格的东西(而不是尝试用 Python 编写 Java)。
如果您自己无法弄清楚为什么类属性会在代码中导致这些问题,那么也许您应该三思而后行地引入这样的语言黑客。 首先更熟悉这门语言可能会更明智。
为了完整起见,这里是槽的文档链接。
You are completely misusing
__slots__
. It prevents the creation of__dict__
for the instances. This only makes sense if you run into memory problems with many small objects, because getting rid of__dict__
can reduce the footprint. This is a hardcore optimization that is not needed in 99.9% of all cases.If you need the kind of safety you described then Python really is the wrong language. Better use something strict like Java (instead of trying to write Java in Python).
If you couldn't figure out yourself why the class attributes caused these problems in your code then maybe you should think twice about introducing language hacks like this. It would probably be wiser to become more familiar with the language first.
Just for completeness, here is the documentation link for slots.
__slots__
使用实例变量,而您拥有的是类变量。 这就是你应该这样做的方式:__slots__
works with instance variables, whereas what you have there is a class variable. This is how you should be doing it:考虑一下这一点。
更好的方法是使用单元测试进行此类检查。 这是相当大的运行时开销。
Consider this.
A better approach is to use unit tests for this kind of checking. This is a fair amount of run-time overhead.
这里的
m
是类属性,而不是实例属性。 您需要在 __init__ 中自行将其与您的实例连接。The
m
here is the class attributes, rather than the instance attribute. You need to connect it with your instance by self in__init__
.