# __init__() 構造方法(或建構函式) # 建構函式可以包含多個引數,但必須包含一個名為self的引數,且必須作為第一個引數 # 建構函式可以手動新增,如果不新增,python也會為類新增一個僅包含self引數的構造方法 class Demo: num1 = '11' num2 = '22' def __init__(self,str1): print("傳入的引數:",str1) def say(self,str2): # 無論是構造方法還是例項方法,都要求將self引數作為方法的第一個引數 print(str2) # 建立物件時,會自動呼叫__init__()構造方法,且self引數是特殊引數,python會自動傳給它值,而'12345'是傳給str1的值 demo = Demo('12345') # 訪問物件的變數和方法 demo.say("呼叫物件的方法") print(demo.num1, demo.num2) # 動態新增類物件的變數 demo.num3 = '33' print('動態新增變數', demo.num3) # 動態刪除類物件的變數del demo1.num3 # 動態修改類物件的變數 demo.num1 = '44' print('動態修改變數', demo.num1) # 動態新增類物件的方法 def say1(): print('動態新增方法') demo.say1 = say1 demo.say1() # 類屬性細分:類屬性、例項屬性、區域性變數 # 類變數(或類屬性):類體中,所有函式之外的變數 # 注:類變數建議用類名呼叫,不建議用物件名呼叫 # 例項變數(或例項屬性):類體中,所有函式內部,以"self.變數名"方式定義的變數 class Demo1: num1 = '類變數1' def __init__(self): self.num1 = '例項變數1' def say(self): self.num2 = '例項變數2' demo1 = Demo1()# 自動呼叫建構函式 print('建構函式中的例項變數:',demo1.num1) demo1.say()# 需要先呼叫函式,才能擁有例項變數 print('例項函式中的例項變數:',demo1.num2) # 類變數和例項變數同名時,物件將無法呼叫類變數,它會首選例項變數 print('物件訪問同名的類變數和例項變數', demo1.num1) print('類訪問同名的類變數和例項變數', Demo1.num1)# 例項變數只能透過物件名訪問,無法透過類名訪問 # 區域性變數:類體中,所有函式內部,以"變數名=變數值"方式定義的變數 # 類方法細分:例項方法、類方法、靜態方法(實際幾乎用不到類方法和靜態方法) # 例項方法:通常情況下,在類中定義的方法預設都是例項方法,至少要包含一個self引數 # 類方法:函式前,需要用@classmethod修飾 # 第一個引數self更名為cls # 類方法建議用類名呼叫,不推薦用物件名呼叫 class Demo2: def __init__(self): self.num1 = '例項變數1' @classmethod def say(cls): print('類呼叫類方法,列印cls變數', cls) Demo2.say() # 靜態方法:就是函式,唯一區別,靜態方法的作用域為類空間,函式的作用域為程式的全域性名稱空間 # 函式前需要用@staticmethod修飾,沒有self和cls這樣的引數 class Demo3: def __init__(self): self.num1 = '例項變數1' @staticmethod def say(): print('呼叫靜態方法') Demo3.say() # 類呼叫例項方法 class Demo4: def __init__(self): self.num1 = '例項變數1' def say(self): print('類呼叫例項方法') demo4 = Demo4() Demo4.say(demo4)# 類呼叫例項方法時,必須手動傳入self引數(物件呼叫例項方法時,python會自動給self值) # python描述符,以下三個方法組成了描述符協議,如果這些方法中的任何一個被定義在一個物件中,這個物件就是一個描述符 # __get__(self,instance,owner):在讀取屬性時將呼叫該方法 # __set__(self,instance,value):在設定屬性時將呼叫該方法 # __delete__(self,instance):對屬性呼叫del時將呼叫該方法 # self:Demo5的例項物件,即myClass的屬性x;instance:myClass的例項物件,即m;owner:myClass這個類,擁有所有這些東西;vlaue:對m.x的賦值,即下面例子中的20 class Demo5: def __init__(self, val = None, name = 'kbq'): self.val = val self.name = name def __get__(self, instance, owner): print("getting",self.name) return self.val def __set__(self, instance, value): print("setting",self.name) self.val = value class myClass: x = Demo5(10,'lm') # 如果一個類的某個屬性有資料描述符,查詢這個屬性時,會呼叫描述符的__get__()方法;對這個熟悉賦值時,也會呼叫__set__()方法。 y = 5 m = myClass() print(m.x) m.x = 20 print(m.x) print(m.y) # 既保護類的封裝特性,又讓開發者可以使用“物件.屬性”的方式操作操作類屬性 # 方法一、property()函式 # 格式:屬性名=property(fget=None, fset=None, fdel=None, doc=None) # 在使用property()函式時,以上4個引數可以僅指定第1個、或者前2個、或者前3個,或者全部指定。 class Demo6: def __init__(self): self.__name = "類的例項化" # name屬性必須設定為私有屬性,即使用__name(前面有2個下劃線) def setname(self,n): self.__name = 3*n def getname(self): return self.__name def delname(self): self.__name = "xxx" aa = property(getname,setname,delname,"指明出處") demo6 = Demo6() print('例項化之後print', demo6.aa) demo6.aa = "呼叫setname()" print('呼叫setname之後print', demo6.aa) del demo6.aa # 呼叫delname() print('呼叫delname之後print', demo6.aa) # 方法二、@proprety裝飾器 class Demo7: def __init__(self): self.__area = "類的例項化" @property # 將area()方法轉化成同名只讀屬性的getter方法 def area(self): return self.__area @area.setter # 將area()方法轉化成同名只讀屬性的setter方法 def area(self,value): self.__area = 3*value @area.deleter # 將area()方法轉化成同名只讀屬性的deleter方法 def area(self): self.__area = "xxx" demo7 = Demo7() print('裝飾器getter之後print',demo7.area) # 透過 @property裝飾器,可以直接透過方法名來訪問方法,不需要在方法名後新增一對“()”小括號 demo7.area = 90 print('裝飾器setter之後print',demo7.area) del demo7.area print('裝飾器deleter之後print',demo7.area) # 繼承,如果該類沒有顯式指定繼承自哪個類,則預設繼承 object 類 # 格式:class 類名(父類1,父類2,...) class people: def say(self): print('父類people的self.name:',self.name) class animal: def display(self): print('父類animal') class Person(people,animal): # 實際使用的時候儘量不要使用多繼承 pass person = Person() person.name = "輸入的名字" person.say() person.display() # 父類方法重寫 # 針對父類方法在子類中不適用的情況,需要對方法進行重寫 class Bird: def isWing(self): print("鳥有翅膀") def fly(self): print("鳥會飛") class Ostrich(Bird): def fly(self): print("鴕鳥不會飛") ostrich = Ostrich() ostrich.fly() Bird.fly(ostrich) # 呼叫父類中的fly() # super()函式,(多個父類時,呼叫的是第一個父類的方法) # 在子類中定義新的構造方法,必須要在該方法中呼叫父類的構造方法(因為子類如果使用父類的方法時,涉及父類構造方法中的屬性時,未呼叫父類構造方法相當於沒有給父類構造方法中的屬性做初始化,則程式執行會報錯),且有以下兩種方法: # 1、未繫結方法:People.__init__(self,name) # 2、super()函式:super().__init__(name) class People: def __init__(self,name): self.name = name def say(self): print("人,名字為:",self.name) class Animal: def __init__(self,food): self.food = food def display(self): print("動物,吃:",self.food) class Person(People, Animal): def __init__(self,name,food): super().__init__(name) # 呼叫People類的構造方法 Animal.__init__(self,food) # 使用未繫結方法呼叫Animal類構造方法 print('5465565454') per = Person("張三", "熟食") per.say() per.display() # __slots__屬性其實是一個元組,只能限制為例項物件動態新增屬性和方法,而無法限制動態地為類新增屬性和方法 class Demo8: __slots__ = ('l') # 意味著該類的例項物件僅限於動態新增'l'這個熟悉或方法 def l(self): print('__slots__為類物件動態新增屬性和方法l') def p(self): print('__slots__為類物件動態新增屬性和方法p') demo8 = Demo8() demo8.l = l demo8.l(demo8) # demo8.p = p # 執行會報錯,只能新增l # type # 用法一:type(obj)檢視變數的型別 # 用法二:type(name,bases,dict)用來建立類 # name表示類的名稱 # bases表示一個元組,用來儲存該類的父類 # dict表示一個字典,用於表示類內定義的屬性或方法 def say(self): print("type建立類") Demo9 = type('Demo9', (object,), {'say':say, 'name':"類中的變數name"}) # (object,)元組中只有一個元素時,最後的逗號不能省略 demo9 = Demo9() demo9.say() print(demo9.name) # MetaClass元類:1、必須顯示繼承type類;2、類中需要定義並實現__new__()方法 # 定義元類 class FirtMetaClass(type): def __new__(cls,name,bases,attrs): attrs['say_'+name] = lambda self,value,saying=name:print(saying+','+value+'!') return type.__new__(cls,name,bases,attrs) # 建立類 class Hello(object,metaclass=FirtMetaClass): pass class Hi(object,metaclass=FirtMetaClass): pass # 建立例項 hello = Hello() hi = Hi() # 呼叫例項 hello.say_Hello('kbq') hi.say_Hi('ora') # 多型,具有不同功能的函式可以使用相同的函式名,這樣就可以用一個函式名呼叫不同內容的函式 class Animal: def talk(self): pass class Cat(Animal): def talk(self): print("喵喵喵") class Dog(Animal): def talk(self): print("汪汪汪") def func(obj): obj.talk() cat = Cat() dog = Dog() func(cat) func(dog) # 列舉類 # 列舉類不能用來例項化物件, from enum import Enum class Color(Enum): red = 1 green = 2 blue = 3 print('呼叫列舉類red:',Color.red) print('呼叫列舉類的name:',Color.green.name) print('呼叫列舉類的value:',Color.green.value) for color in Color: print("遍歷列舉類",color) # Enum()函式可接受2個引數,第一個用於指定列舉類的類名,第二個引數用於指定列舉類中的多個成員 Num = Enum("Num",('one','two','three')) print('用Enum建立列舉類:',Num.one.name,Num.one.value)