Python全棧學習筆記day 26:封裝、property、classmethod、staticmathod
阿新 • • 發佈:2018-11-05
一、封裝
【封裝】隱藏物件的屬性和實現細節,僅對外提供公共訪問方式。
【私有變數】: __名字 (稱為私有化)
私有化了之後,就不能能從類的外部直接呼叫了。
靜態屬性、方法、物件屬性都可以私有化,這種私有化只是從程式碼級別做了變形,並沒有真的約束。
用到私有的場景 :
1.隱藏起一個屬性 不想讓類的外部呼叫
2.我想保護這個屬性,不想讓屬性隨意被改變
3.我想保護這個屬性,不被子類繼承
私有化後的呼叫:
class Person: __key = 123 私有靜態屬性 def __init__(self,name,passwd): self.name = name self.__passwd = passwd 私有屬性 def __get_pwd(self): 私有方法 return self.__passwd 只要在類的內部使用私有屬性,就會自動的帶上_類名 def login(self): 正常的方法呼叫私有的方法 self.__get_pwd() alex = Person('alex','alex3714') print(alex._Person__passwd) _類名__屬性名 print(alex.get_pwd())
物件的私有屬性、類中的私有方法、類中的靜態私有屬性:所有的私有的 都不能在類的外部使用
封裝使用栗子:
class Room: def __init__(self,name,length,width): self.__name = name self.__length = length self.__width = width def get_name(self): return self.__name def set_name(self,newName): 改名字 if type(newName) is str and newName.isdigit() == False: self.__name = newName else: print('不合法的姓名') def area(self): 面積 return self.__length * self.__width jin = Room('金老闆',2,1) print(jin.area()) 2 jin.set_name('2') 不合法的姓名 print(jin.get_name()) 金老闆
這種機制也並沒有真正意義上限制我們從外部直接訪問屬性,知道了類名和屬性名就可以拼出名字:_類名__屬性,然後就可以訪問了(原則上不允許)
二、property
內建裝飾器函式,只在面向物件中使用 可以向訪問資料屬性一樣去訪問area,會觸發一個函式的執行,動態計算出一個值
使用栗子:
當不使用@property時:
from math import pi
class Circle:
def __init__(self,r):
self.r = r
def perimeter(self): 圓的周長
return 2*pi*self.r
def area(self): 圓的面積
return self.r**2*pi
c1 = Circle(5)
print(c1.area) <bound method Circle.area of <__main__.Circle object at 0x008DF150>>
print(c1.perimeter) <bound method Circle.perimeter of <__main__.Circle object at 0x008DF150>>
當使用@property時:
from math import pi
class Circle:
def __init__(self,r):
self.r = r
@property
def perimeter(self): 圓的周長
return 2*pi*self.r
@property
def area(self): 圓的面積
return self.r**2*pi
c1 = Circle(5)
print(c1.area) 78.53981633974483
print(c1.perimeter) 31.41592653589793
注意:此時的特性area和perimeter不能被賦值
c.area=3 為特性area賦值
'''
丟擲異常:
AttributeError: can't set attribute
'''
2.1 @方法名.setter(對類的物件修改)
使用栗子:
class Person:
def __init__(self,name):
self.__name = name
@property
def name(self):
return self.__name + 'sb'
@name.setter
def name(self,new_name):
self.__name = new_name
tiger = Person('泰哥')
print(tiger.name) 泰哥sb
tiger.name = '全班'
print(tiger.name) 全班sb
使用格式:
2.2 @price.deleter(對類的物件刪除)
栗子:
class Goods:
def __init__(self):
self.original_price = 100
self.discount = 0.8
@property
def price(self): 實際價格 = 原價 * 折扣
new_price = self.original_price * self.discount
return new_price
@price.setter
def price(self, value):
self.original_price = value
@price.deleter
def price(self):
del self.original_price
obj = Goods()
obj.price 獲取商品價格
obj.price = 200 修改商品原價
print(obj.price)
del obj.price 刪除商品原價
三、classmethod 類方法
作用:把一個方法 變成一個類中的方法,這個方法就直接可以被類呼叫,不需要依託任何物件 使用情況:當這個方法的操作只涉及靜態屬性的時候 就應該使用classmethod來裝飾這個方法
class Goods:
__discount = 0.8
def __init__(self,name,price):
self.name = name
self.__price = price
@property
def price(self):
return self.__price * Goods.__discount
@classmethod
def change_discount(cls,new_discount): 修改靜態屬性:折扣
cls.__discount = new_discount
apple = Goods('蘋果',5)
print(apple.price)
Goods.change_discount(0.5)
print(apple.price)
類方法:有一個預設引數 cls 代表這個類 cls
四、staticmathod 靜態的方法
在完全面向物件的程式中,如果一個函式 既和物件沒有關係 也和類沒有關係 那麼就用staticmethod將這個函式變成一個靜態方法
栗子:
class Login:
def __init__(self,name,password):
self.name = name
self.pwd = password
def login(self):pass
@staticmethod
def get_usr_pwd(): # 靜態方法
usr = input('使用者名稱 :')
pwd = input('密碼 :')
Login(usr,pwd)
Login.get_usr_pwd()
靜態方法:沒有預設的引數 就象函式一樣
物件可以呼叫類方法和靜態方法麼? 可以,一般情況下 推薦用類名呼叫