python基礎七
- 2019 年 10 月 6 日
- 筆記
無論是風裡,還是在雨里,我都在這裡守候著你~
對於封裝更正
私有方法,和私有屬性,靜態私有屬性
class Person:
__person = '人類'
def __init__(self,name,age):
self.name = name
self.__age = age
def get_age(self):
return self.__age
def set_age(self,newage):
if newage>15:
self.__age = newage
else:
print('年齡需要大於15')
zhangsan = Person('張三',18)
# print(zhangsan.__age) #這樣是調用不到這個屬性的
print(zhangsan.get_age()) # 這樣才是正確的調用方式
__person表示靜態私有屬性,在外部同樣獲取不到。在屬性前加上__表示封裝變成私有屬性,在外部是不能調用的。只能在內部使用,我們再在Person中添加一個方法,用這個方法獲取就可以了。
set_age:我們如果想要修改,如果想要對age有一個約束條件就可以這樣寫。
同樣,我們在Person中的方法名加上一個__,就變成了私有方法,外部無法調用。在子類中也無法去調用。
將調用方法看上去像調用一個屬性
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
p = Person('張三')
print(p.get_name)
@property:內置裝飾器,實現如上效果。
但是get_name不能去傳參數,如果我想要去修改呢?
如下:
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
@get_name.setter
def get_name(self,newname):
self.__name = newname
p = Person('張三')
print(p.get_name)
p.get_name = '李四'
print(p.get_name)
把get_name 當成屬性去修改它即可。
刪除一個屬性:
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
p = Person('張三')
print(p.get_name)
del p.get_name
會被錯,會提示can't delete attribute,不能刪除。
那怎麼樣才能刪除呢:
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
@get_name.deleter
def get_name(self):
print('刪除我')
p = Person('張三')
print(p.get_name)
del p.get_name
print(p.get_name)
執行會輸出:
張三
刪除我
張三
顯然,沒有報錯,但是卻沒有刪除,但是其中執行了刪除我這個方法,也就是說我們在外面del一個屬性(方法)實際上是調用了這個方法,那麼我們將輸出刪除我這個方法修改成:
@get_name.deleter
def get_name(self):
del self.__name
即可。 第二次輸出會報錯:沒有這個屬性。
其他:
1、判斷一個類是不是另一個類的子類:
class A:
pass
class B(A):
pass
print(issubclass(B,A)) # True
是返回True,不是返回False
2、判斷一個對象是否是一個類的對象
class A:pass
a = A()
print(isinstance(a,A)) # True
是返回True ,不是返回False
定義類的規範
當我們想要定義一個類的規範的時候,比如支付寶和衛星都有支付功能,我想寫一個方法,可以調用支付寶和微信的支付功能。
class Wechat:
def pay(self,money):
print('微信支付了%s元'%money)
class Alipay:
def pay(self,money):
print('阿里支付了%s元'%money)
def payzhifu(pay_nei,money):
pay_nei.pay(money)
wechat = Wechat()
p = payzhifu(wechat,100)
輸出:微信支付了100元
看來是沒有毛病的,但是如果再來一個百度支付,而百度的支付方法不是pay,那樣就會報錯,
所以我們需要寫一個類的規範。讓支付類都必須有pay方法。
這樣:
from abc import abstractmethod,ABCMeta
class PayAncestors(metaclass = ABCMeta):
@abstractmethod
def pay(self,money):
pass
class Wechat(PayAncestors):
def pay(self,money):
print('微信支付了%s元'%money)
class Alipay(PayAncestors):
def pay(self,money):
print('阿里支付了%s元'%money)
def payzhifu(pay_nei,money):
pay_nei.pay(money)
wechat = Wechat()
p = payzhifu(wechat,100)
metaclass:指定元類
@abstractmethod:給他一個裝飾器,表示要寫一個類的規範了。
這樣就定義了一個規範,他的子類都必須有pay方法,如果沒有,就會報錯,並提醒沒有pay方法。
報錯提示:Can't instantiate abstract class Wechat with abstract methods pay
我們稱它為介面類。(在python中實際是沒有介面類一說,在別的語言中有,python也可以實現,但是在python里沒有介面類一說。只是模擬了介面類)他也可以叫做抽象類。(在python類中有抽象類,實實在在存在)
介面隔離原則:我們在定義以一個規範的時候,不要使用單一的總介面,也就是說,一個類中不要有多個方法,單一點。
總結:無論是抽象類還是介面類,都是面向對象的開發規範,並且都不能實例化,一般都是單繼承,由於java中沒有多繼承,所以介面類是從java中引來的,java利用創捷介面來規範多繼承。python中不存在介面類一說,只是在python中模擬了一下寫法,但是在python中有抽象類,寫法和上面是一樣的。
類方法
class Person:
__person = '人類'
def __init__(self,name):
self.name = name
def get_person(self,newperson):
Person.__person = newperson
return Person.__person
zhangsan = Person('張三')
print(zhangsan.get_person('動物類'))
如上我們可以發現,當把靜態屬性改為私有,修改的時候我們大概會這樣寫,每次都需要需要Person.xxx來調用和修改,這樣就出來了一個類方法,也就是將self替換成自己這個類對象。於是修改成:
class Person:
__person = '人類'
def __init__(self,name):
self.name = name
@classmethod
def get_person(cls,newperson):
cls.__person = newperson
return Person.__person
zhangsan = Person('張三')
print(zhangsan.get_person('動物類'))
@classmethod:加一個裝飾器表示類方法,不需要去實例化了。
cls:代表這個類本身。
當我們只修改,只需要靜態屬性的時候我們就需要這樣做。
靜態方法
當我們類中的方法沒有用到類中的參數時候,我們可以不需要實例化類,來直接調用。
實例:
class Person:
def __init__(self,name,age)
self.name =name
self.age = age
@staticmethod
def getwrite():
name = input('name:')
age = input('age:')
Person(name,age)
在以前,我們調用需要先這樣:
p = Person('張三'.18)
但是現在我們用@staticmethod聲明他是一個靜態方法之後,我們只需要這樣:
Person.getwrite()即可。
讓我們沒有用到類中的任何參數,就可以這樣定義。
反射
以字元串的形式去獲取變數並操作。和eval相似,但是比eval強大。
class Person:
list = ['星期一','星期二','星期三','星期四']
def fun_one(self):
print('我是第一個方法')
def fun_two(self):
print('我是第二個方法')
如果我們想要拿到list列表,可以這樣:
li = getattr(Person,'list')
輸出:['星期一', '星期二', '星期三', '星期四']
直接輸出一個列表。假如在Person中沒有這個list那不就會報錯了?是的
所以:
if hasattr(Person,'list'):
li = getattr(Person,'list')
hasattr():如果存在會返回True,否則返回False。二者搭配使用即可。
如果想要調用方法:同樣的使用方式,但是獲取到的只是一個記憶體地址,需要加上括弧後執行
class Person:
list = ['星期一','星期二','星期三','星期四']
def fun_one(self):
print('我是第一個方法')
def fun_two(self):
print('我是第二個方法')
p = Person()
func = getattr(p,'fun_one')
func()
反射模組屬性
getattr(模組名,'屬性名')
反射模組方法
ret = getattr(模組名,'方法名')
ret()
總結:什麼是可以反射的?
凡是xxx.qqq格式能獲取到的的都可以,xxx寫在getattr()方法的第一個參數,qqq寫在getattr()的第二個參數。
反射當前頁面的值:
import sys
name = '張三'
print(getattr(sys.modules[__name__],'name'))即可。
方法也就大同小異了。
反射修改
class A:
pass
a = A()
setattr(a,'name','張三')
反射刪除變數
class A:
name = 'lisi'
delattr(A,name)