1. 程式人生 > >Python全棧學習筆記day 26:封裝、property、classmethod、staticmathod

Python全棧學習筆記day 26:封裝、property、classmethod、staticmathod

一、封裝

【封裝】隱藏物件的屬性和實現細節,僅對外提供公共訪問方式。

【私有變數】: __名字    (稱為私有化)

          私有化了之後,就不能能從類的外部直接呼叫了。

          靜態屬性、方法、物件屬性都可以私有化,這種私有化只是從程式碼級別做了變形,並沒有真的約束。

用到私有的場景 :

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()

靜態方法:沒有預設的引數 就象函式一樣

物件可以呼叫類方法和靜態方法麼?   
    可以,一般情況下 推薦用類名呼叫