[英]python when I use the '__slots__'
Recent I study Python,but I have a question about __slots__
. 最近我研究Python,但我有一个关于__slots__
的问题。 In my opinion, it is for limiting parameters in Class, but also limiting the method in Class? 在我看来,它是用于限制Class中的参数,还限制Class中的方法?
For example: 例如:
from types import MethodType
Class Student(object):
__slots__=('name','age')
When I run the code: 当我运行代码时:
def set_age(self,age):
self.age=age
stu=Student()
stu.set_age=MethodType(set_age,stu,Student)
print stu.age
An error has occurred:
stu.set_age=MethodType(set_age,stu,Student)
AttributeError: 'Student' object has no attribute 'set_age'
I want to know, why not use set_age for this class? 我想知道,为什么不在这个类中使用set_age?
Using __slots__
means you don't get a __dict__
with each class instance, and so each instance is more lightweight. 使用__slots__
意味着你没有得到每个类实例的__dict__
,因此每个实例都更轻量级。 The downside is that you cannot modify the methods and cannot add attributes. 缺点是您无法修改方法,也无法添加属性。 And you cannot do what you attempted to do, which is to add methods (which would be adding attributes). 你不能做你想做的事情,即添加方法(这将添加属性)。
Also, the pythonic approach is not to instantiate a MethodType, but to simply create the function in the class namespace. 此外,pythonic方法不是实例化MethodType,而是简单地在类命名空间中创建函数。 If you're attempting to add or modify the function on the fly, as in monkey-patching, then you simply assign the function to the class, as in: 如果您正在尝试动态添加或修改函数,就像在猴子修补中一样,那么您只需将该函数分配给类,如:
Student.set_age = set_age
Assigning it to the instance, of course, you can't do if it uses __slots__
. 当然,如果它使用__slots__
,则无法将其分配给实例。
Here's the __slots__
docs: https://docs.python.org/2/reference/datamodel.html#slots 这是__slots__
文档: https : __slots__
In new style classes, methods are not instance attributes. 在新样式类中,方法不是实例属性。 Instead, they're class attributes that follow the descriptor protocol by defining a __get__
method. 相反,它们是通过定义__get__
方法遵循描述符协议的类属性。 The method call obj.some_method(arg)
is equivalent to obj.__class__.method.__get__(obj)(arg)
, which is in turn, equivalent to obj.__class__.method(obj, arg)
. 调用obj.some_method(arg)
方法等同于obj.__class__.method.__get__(obj)(arg)
,它相当于obj.__class__.method(obj, arg)
。 The __get__
implementation does the instance binding (sticking obj
in as the first argument to method
when it is called). __get__
实现执行实例绑定(在调用obj
时将obj
作为method
的第一个参数)。
In your example code, you're instead trying to put a hand-bound method as an instance variable of the already-existing instance. 在您的示例代码中,您尝试将手动绑定方法作为已存在实例的实例变量。 This doesn't work because your __slots__
declaration prevents you from adding new instance attributes. 这不起作用,因为__slots__
声明阻止您添加新的实例属性。 However, if you wrote to the class instead, you'd have no problem: 但是,如果你写了这个类,你就没有问题:
class Foo(object):
__slots__ = () # no instance variables!
def some_method(self, arg):
print(arg)
Foo.some_method = some_method # this works!
f = Foo()
f.some_method() # so does this
This code would also work if you created the instance before adding the method to its class. 如果在将方法添加到其类之前创建实例,则此代码也可以使用。
Your attribute indeed doesn't have an attribute set_age
since you didn't create a slot for it. 您的属性确实没有属性set_age
因为您没有为它创建插槽。 What did you expect? 你有什么期望?
Also, it should be __slots__
not __slots
(I imagine this is right in your actual code, otherwise you wouldn't be getting the error you're getting). 此外,它应该是__slots__
而不是__slots
(我想这在你的实际代码中是正确的,否则你不会得到你得到的错误)。
Why aren't you just using: 你为什么不只是使用:
class Student(object):
__slots__ = ('name','age')
def set_age(self,age):
self.age = age
where set_age
is a method of the Student
class rather than adding the function as a method to an instance of the Student
class. 其中set_age
是Student
类的方法,而不是将函数作为方法添加到Student
类的实例。
Instead of __slots__
, I'm using the following method. 而不是__slots__
,我使用以下方法。 It allow the use of only a predefined set of parameters: 它只允许使用一组预定义的参数:
class A(object):
def __init__(self):
self.__dict__['a']=''
self.__dict__['b']=''
def __getattr__(self,name):
d=getattr(self,'__dict__')
if d.keys().__contains__(name):
return d.__dict__[attr]
else:
raise AttributeError
def __setattr__(self,name,value):
d=getattr(self,'__dict__')
if d.keys().__contains__(name):
d[name] = value
else:
raise AttributeError
The use of getattr(..)
is to avoid recursion. getattr(..)
是为了避免递归。
There are some merits usin __slots__
vs __dict__
in term of memory and perhaps speed but this is easy to implement and read. 在内存和速度方面,__ __slots__
与__dict__
有一些优点,但这很容易实现和阅读。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.