1. 程式人生 > >Python 類屬性和方法

Python 類屬性和方法

import types


class Dog(object):

    __slots__ = ("name", "color", "info")
                                            #定義__slots__
                                            #該類中只允許 類物件 動態增加 name, color, info, body_len 屬性或方法(都是例項屬性或方法)
                                            #__slots__對類的 動態新增屬性和方法 沒有限制,而 類物件 不能再動態新增物件屬性和方法
                                            #__slots__只對類物件進行限制,不對類進行限制
                                            #_slots__僅對當前類起作用,對繼承的子類不起作用
                                            #__slots__不僅限制類物件的屬性,還限制類物件的方法
                                            #在子類中定義__slots__,子類允許定義的屬性就是自身的__slots__加上父類的__slots__

    company = '藍月公司'                     #company 是類屬性
    len_attr = 1                            #初始化狗的長度

    def __init__(self, name):
        self.name = name
        #name 為例項屬性

    @staticmethod                           #靜態方法可以寫在類內
    def state():
        print("Dog 類的靜態方法(state)")

    @classmethod                            #類方法可以寫在類內
    def get_state(cls):
        print("狗狗的產地是" + cls.address)

    @property
    def body_len(self):
        return self.len_attr

                                            #如果不存在 __slots__ 作為約束,並且類屬性不存在 len_attr 則 property 相當於新定義了一個例項屬性 len_attr
                                            #方法名(body_len)不能與其設定的屬性名(len_attr)相同

    @body_len.setter                        #裝飾器名(body_len.setter)的前半部分必須與上文被裝飾器 property 裝飾的函式(body_len)同名
    def body_len(self, value):              #此處的方法名必須與上文中的被裝飾器裝飾的方法名相同,如果不同也不會報錯,
                                            #因為得到值本質呼叫的是上文被裝飾器property裝飾的函式(函式名並不重要)
                                            #而設定值本質呼叫的是被裝飾器 body_len.setter 裝飾的函式(函式名並不重要)
                                            #但為了能實現 把方法"變成"屬性 ,這裡的函式名必須與上文的函式名同名,否則就失去了裝飾器 @property 存在的意義
        if value > 2:
            print("狗的體長必須小於2米")
        else:
            Dog.len_attr = value

    def get_name(self):
        return self.name

    def set_name(self, name):
        self.name = name

    name_attr = property(fget=get_name, fset=set_name, fdel=None, doc="設定狗的名字")
                                            #property 函式就相當於 @property 裝飾器



d = Dog('薩摩耶')                            #例項化 Dog 物件
e = Dog('土狗')

d.color = 'black'                           #只給 d 物件增加 color 屬性,Dog 基類和其它 Dog 物件並未有 color 屬性

print(hasattr(d, 'color'))                  #判斷 d 物件是否具有 color屬性
print(hasattr(e, 'color'))

Dog.address = '中國'                         #給 Dog 基類增加 address 屬性

print(hasattr(d, 'address'))
print(hasattr(e, 'address'))

def info(self):
    print("產於" + self.address + "的" +self.name + "的顏色為" + self.color)

d.info = types.MethodType(info, d)          #只給 d 物件增加 info 方法,Dog 基類和其它 Dog 物件並未有 info 方法
d.info()                                    #此方法為例項方法

print(hasattr(d, 'info'))
print(hasattr(e, 'info'))

@staticmethod                               #靜態方法可以寫在類外(但必須指定(#000000#))
def show():
    print("Dog 類的靜態方法(show)")

Dog.show = show                             #000000#
Dog.show()
d.show()
e.show()
d.state()
e.state()
Dog.state()

@classmethod
def get_show(cls):                          #cls 只能呼叫 類屬性 而不能呼叫 例項屬性
    print("公司:" + cls.company + " 產地:" + cls.address)
    print(hasattr(cls, 'name'))             #不存在 name 屬性,因為它是 例項屬性

Dog.get_show = get_show
d.get_show()

d.body_len = 3
d.body_len = 1.8
print("當前長度" + str(d.body_len) + "米")

print(d.name_attr)
d.name_attr = "杜賓犬"
print(d.name_attr)