經過裝飾器函數修改一個類屬性python
class MyClass:ide
NAME = 'My CLASS HAHAHA'函數
def __init__(self):測試
passspa
print(MyClass.__dict__['NAME'])orm
My CLASS HAHAHA對象
等價於:get
def setname(name):it
def warpper(cls): io
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}
保護變量
在變量前加一個下劃線,共同的約定,表示提醒你這個是一個內部私有的
而解釋器認爲私有的是私有變量