Python 当我使用'__插槽';

Python 当我使用'__插槽';,python,Python,最近我学习Python,但我有一个关于\uuuuuuuuuuuuuuuuuuuuu的问题。在我看来,这是为了限制类中的参数,但也限制类中的方法 例如: 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,s

最近我学习Python,但我有一个关于
\uuuuuuuuuuuuuuuuuuuuu
的问题。在我看来,这是为了限制类中的参数,但也限制类中的方法

例如:

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?

您的属性确实没有属性
set_age
,因为您没有为它创建插槽。你期待什么


另外,它应该是
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

class Student(object):
    __slots__ = ('name','age')

    def set_age(self,age):
        self.age = age

其中,
set\u age
Student
类的一种方法,而不是将函数作为一种方法添加到
Student
类的实例中。

使用
\uuuuu slots\uuuuuu
意味着每个类实例都不会得到一个
\uuuuu dict\uuu
,因此每个实例都更加轻量级。缺点是不能修改方法,也不能添加属性。你不能做你试图做的事情,也就是添加方法(也就是添加属性)

此外,pythonic方法不是实例化MethodType,而是简单地在类名称空间中创建函数。如果您试图动态添加或修改函数,如在monkey patching中,则只需将函数分配给类,如中所示:

Student.set_age = set_age
当然,将其分配给实例时,如果它使用
\uuuuu插槽
,则无法执行此操作

以下是
\uuuuuuuuuuuuuuuuuu
文档:

在新样式类中,方法不是实例属性。相反,它们是通过定义
\uuu get\uuu
方法遵循的类属性。方法调用
obj.some\u method(arg)
相当于
obj.\uu class\uuuj.method.\uu get\uuj(obj)(arg)
,这反过来又相当于
obj.\uu class\uuj.method(obj,arg)
\uuuu get\uuu
实现执行实例绑定(在调用
方法时,将
obj
作为第一个参数粘贴到
中)

在示例代码中,您将尝试将手动绑定的方法作为已存在实例的实例变量。这不起作用,因为您的
\uuuu\uuu
声明阻止您添加新实例属性。但是,如果您改为向类写信,则不会有任何问题:

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

如果您在将方法添加到其类之前创建了实例,则此代码也可以工作。

我使用以下方法代替
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。它只允许使用一组预定义的参数:

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(..)
是为了避免递归


在内存和速度方面,《代码》与《代码》相比有一些优点,但这很容易实现和阅读。

这似乎已经得到了回答:正如@Thorcourder的链接所说,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
主要用于在创建一大堆属性受约束。你不应该用它来限制用户可以设置的属性。还有一个有趣的问题。赵,欢迎来到StackOverflow!如果我回答了您的问题,您可以通过单击旁边的复选标记来接受它,它将为您的代表添加+2。祝您在学习Python时好运!对不起,我写错了单词“槽”。我已经改正了。虽然这是一个好的观点,但它并不是一个真正的答案。也许您可以更改代码周围的文本,使其成为一个?否则,它可能应该是一个注释(唉,没有代码)。