最近我研究Python,但我对__slots__
有疑问。在我看来,它是限制Class中的参数,但也限制了Class?
例如:
from types import MethodType
Class Student(object):
__slots__=('name','age')
当我运行代码时:
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'
我想知道,为什么不在这个类中使用set_age?
答案 0 :(得分:2)
使用__slots__
表示您没有为每个类实例获取__dict__
,因此每个实例都更轻量级。缺点是您无法修改方法,也无法添加属性。你不能做你想做的事情,即添加方法(这将添加属性)。
此外,pythonic方法不是实例化MethodType,而是简单地在类命名空间中创建函数。如果您正在尝试动态添加或修改该功能,如猴子修补,那么您只需将该功能分配给该类,如:
Student.set_age = set_age
将其分配给实例,当然,如果它使用__slots__
则无法执行。
以下是__slots__
文档:
https://docs.python.org/2/reference/datamodel.html#slots
答案 1 :(得分:1)
在新样式类中,方法不是实例属性。相反,它们是通过定义__get__
方法跟随descriptor protocol的类属性。方法调用obj.some_method(arg)
相当于obj.__class__.method.__get__(obj)(arg)
,而obj.__class__.method(obj, arg)
相当于__get__
。 obj
实现执行实例绑定(在调用method
时将__slots__
作为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
的第一个参数。)
在您的示例代码中,您尝试将手动绑定方法作为已存在实例的实例变量。这不起作用,因为您的{{1}}声明阻止您添加新的实例属性。但是,如果你写了这个课程,你就没有问题了:
{{1}}
如果在将方法添加到类之前创建了实例,则此代码也可以使用。
答案 2 :(得分:0)
您的属性确实没有属性set_age
,因为您没有为其创建插槽。你有什么期望?
此外,它应该是__slots__
而不是__slots
(我想这在你的实际代码中是正确的,否则你不会得到你得到的错误。)
答案 3 :(得分:0)
为什么你不使用:
class Student(object):
__slots__ = ('name','age')
def set_age(self,age):
self.age = age
其中set_age
是Student
类的方法,而不是将函数作为方法添加到Student
类的实例。
答案 4 :(得分:0)
我使用以下方法代替__slots__
。它只允许使用一组预定义的参数:
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
使用getattr(..)
是为了避免递归。
在内存和速度方面,__slots__
vs __dict__
有一些优点,但这很容易实现和阅读。