簡體   English   中英

python當我使用'__slots__'

[英]python when I use the '__slots__'

最近我研究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?

使用__slots__意味着你沒有得到每個類實例的__dict__ ,因此每個實例都更輕量級。 缺點是您無法修改方法,也無法添加屬性。 你不能做你想做的事情,即添加方法(這將添加屬性)。

此外,pythonic方法不是實例化MethodType,而是簡單地在類命名空間中創建函數。 如果您正在嘗試動態添加或修改函數,就像在猴子修補中一樣,那么您只需將該函數分配給類,如:

Student.set_age = set_age

當然,如果它使用__slots__ ,則無法將其分配給實例。

這是__slots__文檔: https__slots__

在新樣式類中,方法不是實例屬性。 相反,它們是通過定義__get__方法遵循描述符協議的類屬性。 調用obj.some_method(arg)方法等同於obj.__class__.method.__get__(obj)(arg) ,它相當於obj.__class__.method(obj, arg) __get__實現執行實例綁定(在調用obj時將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

如果在將方法添加到其類之前創建實例,則此代碼也可以使用。

您的屬性確實沒有屬性set_age因為您沒有為它創建插槽。 你有什么期望?

此外,它應該是__slots__而不是__slots (我想這在你的實際代碼中是正確的,否則你不會得到你得到的錯誤)。

你為什么不只是使用:

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

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

其中set_ageStudent類的方法,而不是將函數作為方法添加到Student類的實例。

而不是__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____dict__有一些優點,但這很容易實現和閱讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM