1. 程式人生 > >裝飾一個類及內部方法

裝飾一個類及內部方法

裝飾類

通過裝飾器函數修改一個類屬性

class MyClass:

NAME = ‘My CLASS HAHAHA‘

def __init__(self):

pass

print(MyClass.__dict__[‘NAME‘])

My CLASS HAHAHA

等價於:

def setname(name):

def warpper(cls):

cls.NAME = name

return cls

return warpper

@setname(‘MY CLASS enen‘) #

class MyClass:

pass

print(MyClass.__dict__[‘NAME‘])

MY CLASS enen

例2:

class MyClass:

def foo(self):

print(‘foo‘)

def bar():

print(‘bar‘)

a = MyClass()

a.bar()

報錯如下:

File "E:\python_project\class_test.py", line 12, in <module>

a.bar()

TypeError: bar() takes 0 positional arguments but 1 was given

提示最少需要給予一個參數才可以

這麽寫的意思是,函數是普通函數,但是實例化之後是無法使用

這樣是不符合規定的

改進:

使用裝飾器,第一個裝飾器使用類方法

@classmethod

class MyClass:

xxx = ‘hahaha‘

def foo(self):

print(‘foo‘)

def bar():

print(‘bar‘)

@classmethod

def clsmtd(cls):

print(‘{}.xxx = {}‘.format(cls.__name__,cls.xxx))

a = MyClass()

a.foo()

MyClass.bar()

print(MyClass.__dict__)

foo

bar

{‘xxx‘: ‘hahaha‘, ‘bar‘: <function MyClass.bar at 0x0000000000DD0488>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘MyClass‘ objects>, ‘__doc__‘: None, ‘foo‘: <function MyClass.foo at 0x0000000000DD0400>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘MyClass‘ objects>, ‘__module__‘: ‘__main__‘, ‘clsmtd‘: <classmethod object at 0x0000000000DD70F0>}

a.clsmtd()

MyClass.xxx = hahaha

靜態方法使用

staticmethod

class MyClass:

def foo(slef):

return(‘foo‘)

def bar():

return(‘bar‘)

@staticmethod

def staticmtd():

return(‘static‘)

a = MyClass()

print(MyClass.staticmtd())

print(a.staticmtd())

static

static

是類的方法即是所有對象的方法

py中的靜態方法,表示最一般的函數放在靜態方法中,但是受其管轄

然後測試bar方法是否可用

@staticmethod

def bar():

return(‘bar‘)

a = MyClass()

print(a.bar())

bar

類方法

class Person:

def haha():

print(‘haha‘)

Person.haha()

haha

由於沒有跟self,沒有完成實例的綁定,所以不能完成實例對象的綁定,所以不能用

Person().haha()

TypeError: haha() takes 0 positional arguments but 1 was given

Person().haha()

語法是對的,但是禁止這麽調用

@classmethod

class Person:

HEIGHT = 16

@classmethod

def class_method(cls):

print(‘class = {0.__name__} ({0})‘.format(cls))

cls.HEIGHT = 17

Person.class_method()

print(Person.HEIGHT)

for i in Person.__dict__.items():

print(i)

返回如下:

class = Person (<class ‘__main__.Person‘>)

17

(‘class_method‘, <classmethod object at 0x0000000000DA1278>)

(‘__weakref__‘, <attribute ‘__weakref__‘ of ‘Person‘ objects>)

(‘__doc__‘, None)

(‘HEIGHT‘, 17)

(‘__module__‘, ‘__main__‘)

(‘__dict__‘, <attribute ‘__dict__‘ of ‘Person‘ objects>)

在類定義中,使用@classmethod裝飾器修飾方法

至少有一個參數,而且第一個參數留給了cls,cls表示調用即類對象自身

cls表示標識符,可以是任意名稱,但是為了易讀性

類方法是可以直接調用,而實例的方法要求實例必須存在,但是類存在的時候實例可能不存在

只要類方法定義過了,類對象就產生了,那麽找屬性即可找到

調用方法總結

代碼如下:

class Person:

def no():

print(‘no‘)

def method(self):

print(‘{} method‘.format(self))

@classmethod

def class_method(cls):

print(‘class = {0.__name__} ({0})‘.format(cls))

cls.HEIGHT = 170

@staticmethod

def static_method():

print(Person.HETGHT)

方法調用

類的調用

print(Person.class_method())

class = Person (<class ‘__main__.Person‘>)

print(Person.static_method())

不能調用

print(tom.method())

<__main__.Person object at 0x0000000000A97160> method

print(tom.class_method())

class = Person (<class ‘__main__.Person‘>)

print(tom.static_method())

不可以,沒有傳遞對象

除了普通方法都可以調用,但是普通方法都需要對象的實例作為第一參數

實例可以調用所有類中定義的方法,類和靜態方法

訪問控制

訪問控制主要為了保護封裝不被破壞,但是python對外是可見的

私有屬性

屬性名前加入兩個下劃線表示當前方法不被破壞

class Person:

age = 3

height = 170

def __init__(self,name,age=18):

self.name = name

self.age = age

def growup(self,incr=1):

if 0 < incr < 150:

self.__age + incr

tom = Person(‘tom‘)

tom.age = 200

class Person:

age = 3

height = 170

def __init__(self,name,age=18):

self.name = name

self.age = age

def growup(self,incr=1):

if 0 < incr < 150:

self.__age + incr

def getage(self):

return self.__age

print(Person(‘tom‘).getage)

<bound method Person.getage of <__main__.Person object at 0x0000000000827208>>

class Person:

def __init__(self,name,age=18):

self.name = name

self.__age = age

def growup(self,incr=1):

if 0 < incr < 150:

self.__age += incr

# 獲取內部屬性

def getage(self):

return self.__age

tom = Person(‘tom‘)

tom.growup(10)

print(tom.getage())

28

修改tom._Person__age

print(tom.getage())

tom._Person__age = 200

print(tom.getage())

200

查看tom.__dict__

print(tom.__dict__)

{‘_Person__age‘: 200, ‘name‘: ‘tom‘}

得到的字典中,其實是新加了一個key,而並非被覆蓋

所以py的外界是可以修改的隱藏方法的

新增加key:

tom._Person__ages = 200

print(tom.getage())

print(tom.__dict__)

{‘name‘: ‘tom‘, ‘_Person__age‘: 20, ‘_Person__ages‘: 200}

私有變量的本質

使用__變量名 時,會將其改名,轉為_類名+前綴,所以原來名字訪問不到了

知道了這個名稱則可以直接修改

print(a.__dict__)

{‘name‘: ‘tom‘, ‘_Person__age‘: 19}

保護變量

在變量前加一個下劃線,共同的約定,表示提醒你這個是一個內部私有的

而解釋器認為私有的是私有變量


裝飾一個類及內部方法