python __slots__和@property
阿新 • • 發佈:2018-12-21
前面瞭解了python的面向物件的基本方式https://blog.csdn.net/qq_21294095/article/details/85118247
心中有挺多的疑問,而解決這些疑問就需要用到python更強大的功能了
一,動態繫結這個事兒太隨意了,怎麼限制?
__slots__屬性可以用來限制動態繫結可以繫結的屬性,哪怕是在類內部,也要遵守這個規定。
class Animal(object): __slots__ = ('name', 'age') def __init__(self, name, legs): self.name = name self.legs = legs animal = Animal('佩奇',4) print(animal.legs) Output: AttributeError: 'Animal' object has no attribute 'legs'
可以看到,因為初始化的時候綁定了__slots__沒有指定的屬性legs,所以出錯。
需要注意:
__slots__會被子類繼承過去,但是子類自己的__slots__沒有做限制,所以父類的__slots__對子類就起不了作用。
class Animal(object): __slots__ = ('name', 'age') def __init__(self, name): self.name = name class Dog(Animal): pass dog = Dog('八公') dog.legs = 4 print(dog.legs) Output: 4
需要在子類也指定__slots__, 然後子類的屬性限定就是父類的並上自己的__slots__
class Animal(object): __slots__ = ('name', 'age') def __init__(self, name): self.name = name class Dog(Animal): __slots__ = ('size') pass dog = Dog('八公') dog.legs = 4 print(dog.legs) Output: AttributeError: 'Dog' object has no attribute 'legs'
二,python中的setter和getter
給類建立了屬性之後,用封裝的思想,那麼就需要提供setter和getter方法。python可以想常規的那樣提供這兩個方法:
class Animal(object):
def getName(self):
return self.name
def setName(self, name):
if isinstance(name, str): #這裡簡單模擬一下設定值的時候的限制 只有是str才可以設定
self.name = name
else:
self.name = '預設名稱'
animal = Animal()
animal.setName(300)
print(animal.getName())
animal.setName('三毛')
print(animal.getName())
Output:
預設名稱
三毛
其實沒什麼問題,就是呼叫的時候有些麻煩。而python是個追求簡單完美的語言,那麼麻煩就不能允許。於是python就提供了一個裝飾器@property來避免這個麻煩
class Animal(object):
@property
def getName(self):
return self.name
@getName.setter
def setName(self, name):
if isinstance(name, str): #這裡簡單模擬一下設定值的時候的限制 只有是str才可以設定
self.name = name
else:
self.name = '預設名稱'
animal = Animal()
animal.setName = 300
print(animal.getName)
animal.setName = '三毛'
print(animal.getName)
Output:
預設名稱
三毛
這裡只做了簡單的修改,可以看到,setter和getter兩個方法名都被裝飾器變成了屬性,並且由於是裝飾器,所以原有的功能都保留了下來。看到這裡,你肯定會說,這有什麼用?感覺程式碼變得更難以理解了。不急,繼續修改下去:
class Animal(object):
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
if isinstance(name, str): #這裡簡單模擬一下設定值的時候的限制 只有是str才可以設定
self.__name = name
else:
self.__name = '預設名稱'
animal = Animal()
animal.name = 300
print(animal.name)
animal.name = '三毛'
print(animal.name)
Output:
預設名稱
三毛
怎麼樣?這下程式碼是不是特別清晰,然而實際上就是把setter和getter方法過載,這樣就有一樣的函式名,接著把真正需要的屬性__私有化,(當然這個私有化前文說過,你有辦法去訪問)而已。如果直接上這段程式碼,會體會不到@property到底做了哪些事情,那麼它做了哪些事情?
- @property 把getter方法變成屬性 並且建立了另一個裝飾器:@屬性.setter
- @屬性.setter 把setter方法變成屬性