[ python ] 封裝

類中的私有屬性

在類中定義一個私有屬性以下:python

class Person(object):
    def __init__(self, name):
        self.__name = name    # 定義私有屬性 self.__name

p = Person('hkey')
print(p.__name)    # 外部不能直接調用私有屬性

執行結果:
Traceback (most recent call last):
  File "E:/learn_python/day26/test6.py", line 11, in <module>
    print(p.__name)
AttributeError: 'Person' object has no attribute '__name'

 

 

私有屬性的使用場景:編程

  1. 隱藏起一個屬性,不想讓類的外部調用
  2. 想要保護這個屬性,不想讓屬性隨便被改變
  3. 保護這個屬性,不被子類繼承

 

雖然私有屬性不能直接從外部調用,可是咱們能夠經過對象.__dict__ 嘗試來獲取這個屬性試試:app

class Person(object):
    def __init__(self, name):
        self.__name = name

p = Person('hkey')
print(p.__dict__)
print(p._Person__name)

執行結果:
{'_Person__name': 'hkey'}    # 執行 p.__dict__ 會直接獲取對象的屬性和方法
hkey    # 在外部能夠經過 p._Person__name 來獲取類中的私有屬性

 

 

使用對象經過 _類名__屬性名 來獲取屬性的方式並不推薦,在python中沒有強制不容許查看類中私有屬性,一切都靠自覺;函數

 

將類中的方法看成屬性查看修改刪除spa

 

 

property  將方法變成屬性


一個實例: 寫一個類,計算圓的周長和麪積3d

from math import pi


class Circle(object):
    def __init__(self, r):
        self.__r = r

    def per(self):    # 圓的周長
        return 2*pi*self.__r

    def area(self):    # 圓的面積
        return pi * self.__r **2

c = Circle(5)
print(c.area())
print(c.per())

 

 

在上面的代碼中,咱們要計算圓的周長和麪積,都是經過對象.方法名() 去獲取的。當咱們使用 property 能夠經過 對象.屬性名 的方式調用函數內的方法,以下:code

from math import pi


class Circle(object):
    def __init__(self, r):
        self.__r = r
    @property    # 經過裝飾器的形式,將類中方法調用的方式修改成函數調用的方式
    def per(self):
        return 2*pi*self.__r
    @property
    def area(self):
        return pi * self.__r **2

c = Circle(5)
print(c.area)
print(c.per)

 

 

屬性能夠從新賦值,可是當使用 property 轉換爲屬性調用的方式後,是不能直接賦值的。對象

class Person(object):
    def __init__(self, name):
        self.__name = name

    @property    # 使用 property 改變類中函數的調用方式
    def name(self):
        return self.__name + ' run.'


p = Person('hkey')
print(p.name)

 

 

setter

 

當咱們要修改對象 p 的 name 屬性時,就須要使用 setterblog

class Person(object):
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name + ' run.'
    @name.setter    # 使用 setter 裝飾器
    def name(self, new_name):
        self.__name = new_name


p = Person('hkey')
print(p.name)
p.name = 'xiaofei'    # 就能夠實現重新賦值
print(p.name)

 

 

當使用 setter 時, 咱們要明確命名規則:繼承

 

當使用 setter 時,咱們不只能夠賦值,還能夠作一些判斷

class Person(object):
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name + ' run.'

    @name.setter
    def name(self, new_name):
        if new_name.isalpha():  # new_name 必須是有字母或漢字組成
            self.__name = new_name


p = Person('hkey')
print(p.name)
p.name = '123'  # 字符串是由數字組成,賦值失敗
print(p.name)

 

 

deleter

 

這個組合中最不經常使用的裝飾器:

做用:當要刪除類中某個屬性的時候使用 deleter 具體使用以下

class Person(object):
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name + ' run.'

    @name.setter
    def name(self, new_name):
        if new_name.isalpha():  # new_name 必須是有字母或漢字組成
            self.__name = new_name
    @name.deleter
    def name(self):
        print('\033[31;1m我要刪除類中【__name】屬性了.\033[0m')
        del self.__name


p = Person('hkey')
del p.name

執行結果:
我要刪除類中【__name】屬性了.

 

 

一個實例, 商品打折的例子。

class Goods(object):
    dicount = 0.5

    def __init__(self, name, price):
        self.name = name
        self.__price = price

    @property
    def price(self):
        return self.__price * Goods.dicount


apple = Goods('apple', 10)
pear = Goods('pear', 5)
print(apple.price)
print(pear.price)

 

 

在上面的實例中,當要改變全部商品的折扣時,只須要修改 dicount, 全部商品的折扣都會改變了。

 

classmethod 類方法

 

當要使用類方法時,須要知足如下兩點:

  1. 把一個方法變成一個類中的方法,這個方法就直接能夠被類調用,不須要依託任何對象
  2. 當一個方法的操做只涉及靜態屬性的時候,就應該使用 classmethod來裝飾這個方法

 

仍是上面商品打折的例子:

dicount 是一個類屬性,咱們就能夠經過定義一個類方法來修改這個屬性

class Goods(object):
    dicount = 0.5

    def __init__(self, name, price):
        self.name = name
        self.__price = price

    @property
    def price(self):
        return self.__price * Goods.dicount

    @classmethod    # 定義一個類方法
    def modify_discount(cls, new_discount):    # cls: 類名,普通形參
        cls.dicount = new_discount

apple = Goods('apple', 10)
pear = Goods('pear', 5)
Goods.modify_discount(0.2)  # 打 0.2 折    # 調用方式 類名.類方法(普通形參)
print(apple.price)
print(pear.price)

執行結果:
2.0
1.0

 

 

staticmethod 靜態方法

 

在徹底面向對象的程序中,若是一個函數即和對象沒有關係,也和類沒有關係。那麼就用 staticmethod 將這個函數變成一個靜態方法

好比在純面向對象的編程中,編寫一個用戶登陸的類:

class Login(object):
    def __init__(self, user, pwd):
        self.user = user
        self.pwd = pwd
    def login(self):
        pass

    @staticmethod    # 靜態方法雖然是在類中,和類是徹底無關的;
    def get_user_pwd():
        user = input('輸入用戶名:')
        pwd = input('輸入密碼:')
        Login(user, pwd)

Login.get_user_pwd()    # 進行登陸

 

 

使用類方法和靜態方法要注意如下幾點:

  1. 類方法和靜態方法 都是類調用的
  2. 對象能夠調用類方法和靜態方法,可是通常建議使用類名去調用
  3. 類方法有一個默認參數 cls 表明這個類,靜態方法 沒有默認的參數 就像函數同樣
相關文章
相關標籤/搜索