文章目錄
面向對象(object)編程
對象是指現實中的物體或實體
面向對象:把一切看成對象(實例),讓對象和對象之間建立關聯關係
對象的特徵:對象有很多的屬性(名詞: 姓名,性別,年齡);
對象有很多行爲(動詞: 學習,吃飯,睡覺,看書)
類
類是擁有相同屬性和行爲的對象分爲一組,即爲一個類,類是用來描述對象的工具,用類可以創建同類對象。
車(類)-----------> BYD E6(京A.88888) 實例
車(類)-----------> BMW X5(京A.00000) 實例
狗(類)----------->小京巴(戶籍號:000001)
----------->導盲犬(戶籍號:000002)
int(類)----------->100(對象/實例)
----------->200(對象/實例)
類的創建語句:
語法:class 類名(繼承列表):
‘’‘類的文檔字符串’’’
實例方法定義(類內的函數稱爲方法method)
類變量定義
類方法定義
靜態方法定義
作用:創建一個類
用於描述詞類對象的行爲和屬性
類用於創建此類的一個或多個對象(實例)
示例:
# 此示例示意類的定義
class Dog: # 定義一個類,類名爲Dog
pass
dog1 = Dog() # 構造函數,創建Dog類的對象
print(id(dog1)) # 4378526216
dog2 = Dog() # 創建Dog類的另一個對象
print(id(dog2)) # 4382983672
# 類似於如下語法:
int1 = int()
int2 = int()
類 對象 實例
class | object | instance
構造函數
表達式:
類名([創建傳參列表])
作用:創建這個類的實例對象,並返回此實例對象的引用關係
實例(對象)說明:實例有自己的作用域和名字空間,可以爲該實例添加實例變量(屬性);實例可以調用類方法和實例方法;實例可以訪問類變量和實例變量
示例:
class Dog:
pass
dog1 = Dog()
實例方法:
語法:
class 類名(繼承列表):
def 實例方法名(self, 參數1, 參數2, …):
‘’‘實例方法的文檔字符串’’’
語句塊
作用:用於描述一個對象的行爲,讓此類型的全部對象都擁有相同的行爲
說明:實例方法實質是函數,是定義在類內的函數;
實例方法至少有一個形參,第一個形參代表調用這個方法的實例, 一般命名爲’self’
實例方法的調用語法:
實例.實例方法名(調用參數)
或
類名.實例方法名(實例,調用傳參)
示例:
# 此實例示意如何用實例方法(method)來描述Dog類的行爲
class Dog:
def eat(self, food):
'''此方法用來描述小狗吃東西的行爲'''
print("小狗正在吃:", food)
def sleep(self, hour):
print("小狗睡了", hour, "小時")
# 創建一個Dog類的實例:
dog1 = Dog()
dog1.eat("狗糧") # 小狗正在吃: 狗糧
dog1.sleep(10) # 小狗睡了 10 小時
# dog1.play("球") # 對象不能調用類內不存在的方法
# 創建另一個Dog對象
dog2 = Dog()
dog2.eat("骨頭")
dog2.sleep(2)
# 可以用下面的方法調用方法
Dog.eat(dog2, '蘋果')
屬性(attribute)
屬性也叫實例變量,每個實例都可以有自己的變量,此變量稱爲實例變量(也叫屬性)
屬性的使用語法:實例.屬性名
賦值規則:首次爲屬性賦值則創建此屬性;再次爲屬性賦值則改變屬性的綁定關係
作用:用來記錄對象自身的數據
實例:
# 此示例示意爲對象添加屬性
class Dog:
pass
# 創建第一個對象
dog1 = Dog()
dog1.kinds = '京巴' # 添加屬性kinds
dog1.color = '白色' # 添加屬性color
dog1.color = '黃色'
print(dog1.color, '的', dog1.kinds) # 訪問屬性
dog2 = Dog()
dog2.kinds = '牧羊犬'
dog2.color = '灰色'
實例方法和實例變量(屬性)結合在一起使用:
示例:
class Dog:
def eat(self, food):
print(self.color, '的', self.kinds, '正在吃', food)
# 創建第一個對象
dog1 = Dog()
dog1.kinds = '京巴' # 添加屬性kinds
dog1.color = '白色' # 添加屬性color
dog1.color = '黃色'
#print(dog1.color, '的', dog1.kinds) # 訪問屬性
dog1.eat('骨頭')
dog2 = Dog()
dog2.kinds = '牧羊犬'
dog2.color = '灰色'
dog2.eat('包子')
class Student:
def set_info(self, name, age=0):
'''此方法用來給學生對象添加姓名和年齡屬性'''
self.name = name
self.age = age
return self.name, self.age
def show_info(self):
'''此處顯示學生的信息'''
print(self.name, '今年', self.age, '歲')
s1 = Student()
s1.set_info('xiaomaomao', 1)
s2 = Student()
s2.set_info('xiaoxiaomao', 1)
s1.show_info()
s2.show_info()
刪除屬性
用del語句可以刪除一個對象的實例變量
語法:del 對象.實例變量名
示例:
class Cat:
pass
cat1 = Cat() # 創建對象
c1.color = '白色' # 添加屬性
print(c1.color)
del c1.color # 刪除屬性
print(c1.color) # 屬性錯誤
初始化方法
作用:對新創建的對象添加實例變量(屬性)或相應的資源
語法格式:class 類名(繼承列表):
def init(self [, 形參列表])
語句塊
說明:(1) 初始化方法名必須__init__不可改變;
(2) 初始化方法會在構造函數創建實例後自動調用,且實例自身通過第一個參數self傳入__init__方法;
(3) 構造函數的實參將通過__init__方法的形參列表傳入__init__方法中;
(4) 初始化方法內部如果需要返回則只能返回None
示例:
# 此示例示意__init__方法的自動調用及添加示例變量
class Car:
def __init__(self, c, b, m):
self.color = c # 顏色
self.band = b # 品牌
self.model = m # 型號
def run(self, speed):
print(self.color, '的', self.band, self.model,
'正在以', speed, '公里/小時的速度行駛')
def set_color(self, clr):
'''此方法用來修改車的顏色信息'''
self.color = clr
a4 = Car('紅色', '奧迪', 'A4')
a4.run(179) # # 紅色 的 奧迪 A4 正在以 179 公里/小時的速度行駛
#a4.color = '黑色'
a4.set_color('黑色')
a4.run(300) # 黑色 的 奧迪 A4 正在以 300 公里/小時的速度行駛
t1 = Car('藍色', 'TESLA', 'Modle S')
t1.run(299) # 藍色 的 TESLA Modle S 正在以 299 公里/小時的速度行駛
# a4.__init__('白色', 'Tesla', 'Model S') # 顯式調用__init__
析構方法
語法:
class 類名(繼承列表):
del(self):
語句塊
說明:析構方法在對象銷燬時被自動調用
作用:清理此對象所佔用的資源
示例:
# 此示例示意__del__方法的用法
class Car:
def __init__(self, name):
self.name = name
print("汽車", name, "對象已經創建")
def __del__(self):
print(self.name, "對象已經銷燬")
c1 = Car("BYD") # 汽車 BYD 對象已經創建
c1 = Car("BMW")
python不建議在析構方法內做任何事情,因爲對象銷燬的時間難以確定。
預置實例屬性
__dict__屬性:此屬性綁定一個存儲此實例自身變量的字典
示例:
class Dog:
pass
dog1 = Dog() # 創建一個Dog類型的實例
print(dog1.__dict__) # {}
dog1.kinds = '京巴'
print(dog1.__dict__) # {'kinds': '京巴'}
dog1.color = '白色'
print(dog1.__dict__) # {'kinds': '京巴', 'color': '白色'}
print(dog1.color) # 白色
__class__屬性: 此屬性用來綁定創建此實例的類
作用:可以藉助此屬性來訪問創建此實例的類
示例:
class Dog:
pass
dog1 = Dog()
print(dog1.__class__) # <class '__main__.Dog'>
dog2 = Dog()
dog3 = dog1.__class__() # 等同於dog1 = Dog(),創建dog1的同類對象
下面示例示意如何用面向對象的方式創建對象,並建立對象與對象之間的邏輯關係
# 此示例示意如何用面向對象的方式創建對象,並建立對象與對象之間的邏輯關係
class Human:
'''人類,用於描述人的行爲'''
def __init__(self, n, a):
self.name = n # 姓名
self.age = a # 年齡
self.money = 0 # 錢數爲0
def teach(self, other, skill):
print(self.name, "教", other.name, "學", skill)
def works(self, money):
self.money = self.money + money
print(self.name, "工作賺了", self.money, "元錢")
def borrow(self, other, money):
if other.money > money:
print(other.name, "借給", self.name, money, "元錢")
self.money = self.money + money
other.money = other.money - money
else:
print(other.name, "不借給", self.name, "錢")
def show_info(self):
print(self.age, "歲的", self.name, "存有", self.money, "元錢")
# 以下爲類的使用
xiaomaomao = Human('xiaomaomao', 1)
xiaoxiaomao = Human('xiaoxiaomao', 1)
xiaoxiaomao.teach(xiaomaomao, 'Python') # xiaoxiaomao 教 xiaomaomao 學 Python
xiaomaomao.teach(xiaoxiaomao, 'Java') # xiaomaomao 教 xiaoxiaomao 學 Java
xiaoxiaomao.works(1000) # xiaoxiaomao 工作賺了 1000 元錢
xiaomaomao.borrow(xiaoxiaomao, 200) # xiaoxiaomao 借給 xiaomaomao 200 元錢
xiaoxiaomao.show_info() # 1 歲的 xiaoxiaomao 存有 800 元錢
用於類的函數
isinstance(obj, class_or_tuple) # 返回這個對象obj是否某個類class或某些類的實例,如果是則返回True,如果否則返回False
type(obj) # 返回對象的類型
class Dog:
pass
class Cat:
pass
animal = Dog()
isinstance(animal, Dog)
isinstance(animal, Cat)
isinstance(animal, (Cat, int, list)) # False
isinstance(animal, (Cat, int, Dog)) # True
type(animal) # <class '__main__.Dog'>, 等同於animal.__class__
類變量 class variable(也叫類屬性)
類變量是類的屬性,此屬性屬於類
作用:用來記錄類的相關數據
說明:類變量可以通過類直接訪問;類變量可以通過類的實例直接訪問;類變量可以通過此類的實例的__class__屬性間接訪問
示例:
# 此示例示意類變量的定義和使用
class Human:
count = 0 # 創建一個類變量
# 通過類直接訪問
print("Human的類變量count=", Human.count) # Human的類變量count= 0
Human.count = 100
print(Human.count) # 100
# 通過類的實例直接訪問類變量
human1 = Human()
print(human1.count) # 100
# 通過類示例.__class__訪問類變量
human2 = Human()
human2.count = 200
print(human2.count) # 200
print(human2.__class__.count) # 100
類變量的應用案例:用類變量來記錄對象的個數
class Car:
count = 0 # 創建類變量,用來記錄汽車對象的總數
def __init__(self, info):
print(info, "被創建")
self.data = info # 記錄傳入數據
self.__class__.count = self.__class__.count + 1 # 讓車的總數加1
def __del__(self):
print(self.data, "被銷燬")
self.__class__.count = self.__class__.count - 1 # 當車被銷燬時自動減1
print(Car.count) # 0
b1 = Car("BYD")
print(Car.count) # 1
b2 = Car("BMW")
print(Car.count) # 2
b3 = Car("Audi")
print(Car.count) # 3
類的文檔字符串
類內第一個沒有賦值給任何變量的字符串是類的文檔字符串
說明:類的文檔字符串用類的__doc__屬性可以訪問;類的文檔字符串可以用help()函數查看
示例:
'''
模塊的標題
此模塊示意類的文檔字符串
'''
class Car:
'''
此類用來描述車的對象的行爲
這是Car類的文檔字符串
'''
def run(self, speed):
'''
車的run方法
'''
pass
類的__slots__列表
作用:限定一個類的實例只能有固定的屬性(實例變量),通常爲防止錯寫屬性名而發生運行時錯誤
示例:
# 此示例示意類變量__slots__列表的作用
class Student:
__slots__ = ['name', 'score']
def __init__(self, name, score):
self.name = name
self.score = score
s1 = Student('xiaomaomao', 100)
print(s1.score) # 100
s1.socre = 90 # 不加slots時寫錯了屬性名,但在運行時不會報錯;添加了slots列表後運行會報錯
print(s1.score) # 100
說明:含有__slots__列表的類創建的實例對象沒有__dict__屬性,即此實例不用字典保存對象的屬性(實例變量)
類方法 @classmethod
類方法是描述類的行爲的方法,類方法屬於類
說明:(1)類方法需要用@classmethod裝飾器定義;(2)類方法至少有一個形參,第一個形參用於綁定類,約定寫爲’cls’; (3)類和該類的實例都可以調用類方法;(4)類方法不能訪問此類創建的實例的屬性(只能訪問類變量)
示例:
# 此示例示意類方法的定義和用法
class Car:
count = 0 # 類變量
@classmethod
def getTotalCount(cls):
'''此方法爲類方法,第一個參數爲cls,代表調用此類方法'''
return cls.count
@classmethod
def updateCount(cls, number):
cls.count = cls.count + 1
print(Car.getTotalCount()) # 用類來調用類方法 0
#Car.count = Car.count + 1 # 不提倡直接直接操作類變量
Car.updateCount(1) # 使用類方法操作類變量
print(Car.getTotalCount()) # 1
c1 = Car() # 創建一個對象
c1.updateCount(100) # Car類的實例也可以調用類方法
print(c1.getTotalCount()) # 101
# 此示例示意類方法的定義和用法
class Car:
count = 0 # 類變量
@classmethod
def getInfo(cls):
return cls.count
c1 = Car() # 創建一個對象
c1.count = 100
print(c1.getInfo()) # 0 拿到的是類裏面的變量
靜態方法 @staticmethod
問題:(1)類方法屬於類
(2) 實例方法屬於該類的實例
(3) 類內能不能有函數,這個函數不屬於類,也不屬於實例。這樣的方法是靜態方法。
靜態方法不屬於類,也不屬於類的實例,它相當於定義在類內的普通函數,只是它的作用域屬於類
示例:
# 此示例示意靜態方法的創建和使用
class A:
@staticmethod
def myadd(x, y):
'''
此方法爲靜態方法
此方法的形參不需要傳入類或實例
'''
return x + y
print('1+2=', A.myadd(1, 2))
a = A()
print('100+200=', a.myadd(100, 200))
繼承(inheritance)和派生(derived)
繼承:繼承是指從已有的類中派生出新類,新類具有原類的行爲,並能擴展新的行爲。
派生:派生是從一個已有類中衍生(創建)新類, 在新類上可以添加新的屬性和行爲
繼承和派生的目的:繼承是延續舊類的功能;派生是爲了在舊類的基礎上添加新的功能
作用:
(1)用繼承派生機制,可以將一些共有功能加在基類中,實現代碼的共享
(2) 在不改變基類的基礎上改變原有功能
繼承/派生的名詞:
基類(base class),超類(super class),父類(father class),派生類(derived class),子類(child class)
單繼承
語法:
class 類名(基類名):
語句塊
說明:單繼承是指派生類由一個基類衍生出來的類
示例:
class Human:
'''此類用來描述人類的共性行爲'''
def say(self, that):
print("say: ", that)
def walk(self, distance):
print("walk: ", distance, "kms")
class Student(Human):
def study(self, subject):
print("studying: ", subject)
class Teacher(Student):
def teach(self, subject):
print("teaching: ", subject)
h1 = Human()
h1.say("todday is very cold")
h1.walk(5)
s1 = Student()
s1.say("todday is very cold")
t1 = Teacher()
t1.say("tommorrow is Saturday")
t1.walk(6)
t1.teach("object oriented")
t1.study("piano")
繼承說明:任何類都直接或間接繼承自object類,object類是一切類的超類(祖類)
類的__base__屬性:__base__屬性用來記錄此類的基類
覆蓋(override)
覆蓋:覆蓋是指在有繼承關係中的類中,子類中實現了與基類同名的方法,在子類實例調用該方法時,實例調用的是子類中的覆蓋版本的方法,這種現象叫做覆蓋。
示例:
# 此示例示意覆蓋的用法
class A:
def work(self):
print("A.work()被調用")
class B(A):
'''B繼承自A類'''
def work(self):
print("B.work()被調用")
a = A()
a.work() # A.work()被調用
b = B()
b.work() # B.work()被調用
b.__class__.__base__.work(b) # A.work()被調用
子類對象顯式調用基類方法的方式:
基類名.方法名(實例, 實例調用傳參)
super函數:
super(type, obj)返回綁定超類的實例
super()返回綁定超類的實例,等同於super(class, 實例方法的第一個參數)(必須在方法內調用)
示例:
# 此示例示意super函數來調用父類的覆蓋版本方法
class A:
def work(self):
print("A.work()被調用")
class B(A):
'''B繼承自A類'''
def work(self):
print("B.work()被調用")
def super_work(self):
# 在方法內調用父類的方法
# self.work() # B.work()
# super(B, self).work() # A.work()
super().work() # A.work()
b = B()
b.__class__.__base__.work(b) # 調用父類的work方法 A.work()被調用
super(B, b).work() # 調用超類的方法 A.work()被調用
b.super_work() # A.work()被調用
顯示調用基類的初始化方法:
當子類中實現了__init__方法時,基類的__init__方法並不會被自動調用,此時需要顯式調用。
示例:
# 此示例示意子類對象用super方法顯示調用基類的__init__方法
class Human:
def __init__(self, n, a):
'''此方法爲人的對象添加姓名和年齡屬性'''
self.name = n
self.age = a
def infos(self):
print("name: ", self.name)
print("age: ", self.age)
class Student(Human):
def __init__(self, n, a, s=0):
super().__init__(n, a)
self.score = s
def infos(self):
super().infos()
print("score: ", self.score)
s1 = Student("xiaoxiaomao", 1, 100)
s1.infos()
用於類的函數
issubclass(cls, class_or_tuple): 判斷一個類是否繼承自其它的類,如果此類cls是class或tuple中的一個派生子類則返回True,否則返回False
示例:
class A:
pass
class B(A):
pass
class C(B):
pass
issubclass(C, (A, B)) # True
issubclass(C, (int, str)) # False
issubclass(C, A) # True
查看python內建類的繼承關係的方法:
help(builtins)
封裝 enclosure
封裝是指隱藏類的實現細節,讓使用者不用關心這些細節,封裝的目的是讓使用者儘可能少的使用實例變量(屬性)進行操作。
私有屬性:python類中,以雙下劃線‘__’開頭,不以雙下劃線結尾的標識符爲私有成員,在類的外部無法直接訪問。
# 此類示意使用私有屬性和私有方法
class A:
def __init__(self):
self.__p1 = 100 # __p1爲私有屬性,在類的外部不可以訪問
def test(self):
print(self.__p1) # 可以訪問,A類的方法可以調用A類的私有方法
def __m1(self):
'''私有方法,只有在類的內部方法才能調用此方法'''
print("我是A類的__m1方法")
a = A() # 創建對象
#print(a.__p1) # 在類外看不到__p1屬性,訪問失敗
a.test() # 100
a.__m1() # 出錯,無法調用私有方法
多態(polymorphic)
字面意思:“多種狀態”
多態是指在繼承/派生關係的類中,調用基類對象的方法,實現能調用子類的覆蓋版本方法的現象叫多態
說明:多態調用的方法與對象相關,不與類型相關;Python的全部對象都只有“運動時狀態(動態)”,沒有“C++/Java”裏的“編譯時狀態(靜態)”
示例:
# 此示例示意多態
class Shape:
def draw(self):
print("Shape.draw被調用")
class Point(Shape):
def draw(self):
print("正在畫一個點")
class Circle(Point):
def draw(self):
print("正在畫一個圓")
def my_draw(s):
s.draw() # 調用那個類具體要看傳進來的參數是哪個類中的
s1 = Circle()
s2 = Point()
my_draw(s1) # 調用Circle裏的draw
my_draw(s2) # 調用Point裏的draw
多繼承 multiple inheritance
多繼承是指一個子類繼承自兩個或兩個以上的基類
語法:
class 類名(基類名1, 基類名2, …):
語句塊
說明:(1) 一個子類同時繼承自多個父類,父類中的方法可以同時被繼承下來;
(2) 如果兩個父類中有同名的方法,而在子類中又沒有覆蓋此方法時,調用結果難以確定
示例:
# 此示例示意多繼承語句和使用
class Car:
def run(self, speed):
print("以", speed, "公里/小時的速度行駛")
class Plane:
def fly(self, height):
print("飛機以海拔", height, "的高度飛行")
class PlaneCar(Car, Plane):
'''
PlaneCar同時繼承自汽車類和飛機類
'''
p1 = PlaneCar()
p1.fly(10000)
p1.run(300)
多繼承的問題(缺陷)
標識符(名字空間衝突的問題),要謹慎使用多繼承
示例:
# 此示例示意多繼承可能出現的問題
# 小貓貓寫了一個類A
class A:
def m(self):
print("A.m()被調用")
# 小小貓寫了一個類B
class B:
def m(self):
print("B.m()被調用")
# 詩詩用小貓貓和小小貓寫的類
class AB(A, B):
pass
ab = AB()
ab.m() # A.m()被調用,但是B.m()中也有m方法,在實際複雜的問題中很難控制哪一個被調用
多繼承的MRO(method resolution order)問題
類內的__mro__屬性用來記錄繼承方法的查找順序
示例:
# 此示例示意在多繼承中的方法查找順序問題
class A:
def m(self):
print("A.m")
class B:
def m(self):
print("B.m")
class C(A):
def m(self):
print("C.m")
super().m() # super()是按照MRO順序來打印的,而不是按照父類的繼承來調用的
class D(B, C):
def m(self):
print("D.m")
super().m()
d = D()
print(D.__mro__) # (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
d.m() # 調用方法的順序D,B,C,A
函數重寫 override
重寫是指在自定義的類內添加相應的方法,讓自定義的類生成的對象(實例)像內建對象一樣進行內建的函數操作
對象轉字符串函數重寫:
repr(obj)返回一個能代表此對象的表達式字符串,通常eval(repr(obj)) == obj
def repr(self):
return 能夠表達self內容的字符串
str(obj)通過給定的對象返回一個字符串(這個字符串通常是給人看的)
示例:
def str(self):
return 人能看懂的字符串
# 沒有重寫str和repr方法前調用str方法
class MyNumber:
def __init__(self, value):
self.data = value
n1 = MyNumber(100)
print(str(n1)) # 調用object的str方法
print(repr(n1)) # 調用object的repr方法
# 打印出如下結果
# <__main__.MyNumber object at 0x10d9f0668>
# <__main__.MyNumber object at 0x10d9f0668>
# 重寫str和repr方法
class MyNumber:
def __init__(self, value):
self.data = value
def __str__(self):
return "數字:%d" % self.data
def __repr__(self):
return 'MyNumber(%d)' % self.data
n1 = MyNumber(100)
print(str(n1)) # 數字:100
print(repr(n1)) # MyNumber(100)
n2 = eval("MyNumber(100)")
print(n2) # 數字:100
說明:
(1) str(obj)函數優先調用obj.str()方法返回字符串
(2) 如果obj沒有__str__()方法,則調用obj.repr()方法返回的字符串
(3) 如果obj沒有__repr__()方法,則調用object類的__repr__()實例方法顯示格式的字符串
數值轉換函數的重寫
complex(self): complex(obj) 函數調用
int(self): int(obj) 函數調用
float(self): float(obj) 函數調用
bool(self): bool(obj) 函數調用
示例:
# 此示例示意自定義的類MyNumber能夠轉爲數字值類型
class MyNumber:
def __init__(self, v):
self.data = v
def __repr__(self):
return "MyNumber(%d)" % self.data
def __int__(self):
'''此方法用於int(obj)函數重載,必須返回整數
此方法通常用於制訂自定義對象如何轉爲整數的規則'''
return 10000
n1 = MyNumber(100)
print(type(n1)) # <class '__main__.MyNumber'>
n = int(n1)
print(type(n)) # <class 'int'>
內建函數的重寫
abs abs(obj)
len len(obj)
reversed reversed(obj)
round round(obj)
示例:
# 自定義一個MyList類,與系統內建的類一樣,用來保存有先後順序關係的數據
class MyList:
'''自定義列表類'''
def __init__(self, iterator=[]):
self.data = [x for x in iterator]
def __repr__(self):
return "MyList(%r)" % self.data
def __abs__(self):
#return MyList([abs(x) for x in self.data])
# 也可以用生成器表達式來生成
return MyList((abs(x) for x in self.data))
def __len__(self):
return len(self.data)
myl = MyList([1, -2, 3, -4])
print(myl)
print(abs(myl))
myl2 = MyList(range(10))
print(myl2)
print('myl2 的長度是:', len(myl2))
print('myl 的長度是:', len(myl))
布爾測試函數的重寫
格式:def bool(self):
…
作用:用於bool(obj)函數取值;
用於if語句真值表達式中
用於while語句真值表達式中
說明:(1) 優先調用__bool__()方法取值
(2) 如果不存在__bool__()方法,則用__len__()方法取值後判斷是否爲零值,如果不爲零返回True,否則返回False
(3) 如果再沒有__len__()方法,則直接返回True
示例:
# 自定義一個MyList類,與系統內建的類一樣,用來保存有先後順序關係的數據
class MyList:
'''自定義列表類'''
def __init__(self, iterator=[]):
self.data = [x for x in iterator]
def __repr__(self):
return "MyList(%r)" % self.data
def __abs__(self):
#return MyList([abs(x) for x in self.data])
# 也可以用生成器表達式來生成
return MyList((abs(x) for x in self.data))
# def __len__(self):
# return len(self.data)
def __bool__(self):
return False
myl = MyList([1, -2, 3, -4])
print(bool(myl)) # 沒有bool方法就用len方法,不爲0返回真;沒有len時永遠返回真;如果有bool方法,優先調用bool方法
if myl:
print("myl 是真值")
else:
print("myl 是假值")