本系列定位爲複習筆記,某些內容並未提及。
在此記錄一些典型疑問和我在學習中的問題或經常遺忘的細節,也會添加一些覺得有意思的部分(其實就是隨心所欲 )
對象
python無處不對象,對象是類的實例化
類包含屬性和方法,實例對象也包含屬性和方法,類本身也是一個類對象,類是type的實例化對象
通過將類實例化,如定義一個魚類,我們就能得到多個魚對象,並對個魚對象進行相應的屬性與方法的操作,如賦予每條魚不同的座標等。
定義類
Python中的類名約定以大寫字母開頭
屬性及烏龜的顏色,體重等特徵
方法則對應我的烏龜對象可以有哪些操作
通過.
來對方法或屬性進行訪問
class
關鍵字
定義一隻烏龜:
class Turtle:
# 定義屬性
color = 'green'
weight = 10
legs = 4
shell = True
mouth = '大嘴'
# 定義方法
def climb(self):
print('我正在很努力的向前爬...')
def run(self):
print('我正在飛快的向前跑...')
def bite(self):
print('咬死你咬死你!!')
def eat(self):
print('有得喫,真滿足...')
def sleep(self):
print('困了,睡了,晚安,zzz')
tt = Turtle()# 實例化過程
print(tt)
# <__main__.Turtle object at 0x0000007C32D67F98>
print(type(tt))
# <class '__main__.Turtle'>
print(tt.__class__)
# <class '__main__.Turtle'>
print(tt.__class__.__name__)
# Turtle
tt.climb()
# 我正在很努力的向前爬...
tt.run()
# 我正在飛快的向前跑...
tt.bite()
# 咬死你咬死你!!
# Python類也是對象。它們是type的實例
print(type(Turtle))
# <class 'type'>
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
多態
多態:不同對象對同一方法響應不同的行動
即調用方法時通過.
來確定在哪個類或對象中來找這個方法,即使方法名相同,但所屬的對象或類不同,則互不干擾
class Animal:
def run(self):
raise AttributeError('子類必須實現這個方法')
class People(Animal):
def run(self):
print('人正在走')
class Pig(Animal):
def run(self):
print('pig is walking')
class Dog(Animal):
def run(self):
print('dog is running')
def func(animal):
animal.run()
func(Pig())
# pig is walking
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
方法中的self
類的方法與普通的函數只有一個特別的區別 —— 它們必須有一個額外的第一個參數名稱(對應於該實例,即該對象本身),按照慣例它的名稱是 self。在調用方法時,我們無需明確提供與參數 self 相對應的參數。
也即
在調用方法時,self參數會自動傳入方法作爲第一個參數,而不需要我們再輸入self參數。
class Ball:
def setName(self, name):
self.name = name
def kick(self):
print("我叫%s,該死的,誰踢我..." % self.name)
a = Ball()
a.setName("球A")
b = Ball()
b.setName("球B")
c = Ball()
c.setName("球C")
a.kick()
# 我叫球A,該死的,誰踢我...
b.kick()
# 我叫球B,該死的,誰踢我...
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
另外
方法中如果要訪問屬性,即調用屬性的值,需要加上self
class Ball:
a=1
def setName(self):
name=a #self.a 纔對
>>> a=Ball()
>>> a.a
1
>>> a.setName()
>>> a.name
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
a.name
AttributeError: 'Ball' object has no attribute 'name'
>>>
Python的魔法方法
點擊查看常用的魔法方法及其使用方式
Python魔方方法即一類特殊的方法,該方法不能被主動調用,而是在某些情況下自動調用
如,當類實例化時,對象屬性值被修改時,對象被刪除時等情況
方法於屬性的定義位置沒有要求
本例中所涉及的__init__(self[, param1, param2...])
方法,該方法在類實例化時會自動調用,對對象的屬性值進行設置。
class Ball:
def __init__(self):
self.name=1
a=1
>>> B=Ball()
>>> B.name
1
>>> B.__init_()
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
B.__init_()
AttributeError: 'Ball' object has no attribute '__init_'
公有和私有
在 Python 中定義私有變量只需要在變量名或函數名前加上“__”兩個下劃線,那麼這個函數或變量就會爲私有的了。
私有屬性與方法只能在對象的內部進行隱藏調用,而不能在對象外進行調用
私有屬性設置:
class JustCounter:
__secretCount = 0 # 私有變量
publicCount = 0 # 公開變量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count() # 1
counter.count() # 2
print(counter.publicCount) # 2
print(counter._JustCounter__secretCount) # 2 Python的私有爲僞私有
print(counter.__secretCount)
# AttributeError: 'JustCounter' object has no attribute '__secretCount'
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
私有方法設置:
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('這是私有方法')
def foo(self): # 公共方法
print('這是公共方法')
self.__foo()
x = Site('老馬的程序人生', 'https://blog.csdn.net/LSGO_MYP')
x.who()
# name : 老馬的程序人生
# url : https://blog.csdn.net/LSGO_MYP
x.foo()
# 這是公共方法
# 這是私有方法
x.__foo()
# AttributeError: 'Site' object has no attribute '__foo'
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
繼承機制
繼承:子類自動共享父類之間數據和方法的機制
即將父類的方法和屬性直接複製到子類中
class MyList(list):
pass
lst = MyList([1, 5, 2, 7, 8])
lst.append(9)
lst.sort()
print(lst)
# [1, 2, 5, 7, 8, 9]
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
繼承其他模塊的類
class DerivedClassName(modname.BaseClassName):
<statement-1>
.
.
.
<statement-N>
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
如果子類中定義與父類同名的方法或屬性,則會自動覆蓋父類對應的方法或屬性。
# 類定義
class people:
# 定義基本屬性
name = ''
age = 0
# 定義私有屬性,私有屬性在類外部無法直接進行訪問
__weight = 0
# 定義構造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 說: 我 %d 歲。" % (self.name, self.age))
# 單繼承示例
class student(people):
grade = ''
def __init__(self, n, a, w, g):
# 調用父類的構函
people.__init__(self, n, a, w)
self.grade = g
# 覆寫父類的方法
def speak(self):
print("%s 說: 我 %d 歲了,我在讀 %d 年級" % (self.name, self.age, self.grade))
s = student('小馬的程序人生', 10, 60, 3)
s.speak()
# 小馬的程序人生 說: 我 10 歲了,我在讀 3 年級
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
注意此處people.__init__(self, n, a, w)
的作用是防止__init__
方法被子類完全覆蓋掉
如:
class Fish:
def __init__(self):
self.x = r.randint(0, 10)
self.y = r.randint(0, 10)
def move(self):
self.x -= 1
print("我的位置", self.x, self.y)
class GoldFish(Fish): # 金魚
pass
class Carp(Fish): # 鯉魚
pass
class Salmon(Fish): # 三文魚
pass
class Shark(Fish): # 鯊魚
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print("喫貨的夢想就是天天有得喫!")
self.hungry = False
else:
print("太撐了,喫不下了!")
self.hungry = True
g = GoldFish()
g.move() # 我的位置 9 4
s = Shark()
s.eat() # 喫貨的夢想就是天天有得喫!
s.move()
# AttributeError: 'Shark' object has no attribute 'x'
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
解決方法:
如上,在__init__
方法中添一句Fish.__init__(self)
或super().__init__()
super()
代指父類
多繼承
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
需要注意圓括號中父類的順序,若是父類中有相同的方法名,而在子類使用時未指定,Python從左至右搜索,即方法在子類中未找到時,從左到右查找父類中是否包含方法。
# 類定義
class People:
# 定義基本屬性
name = ''
age = 0
# 定義私有屬性,私有屬性在類外部無法直接進行訪問
__weight = 0
# 定義構造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 說: 我 %d 歲。" % (self.name, self.age))
# 單繼承示例
class Student(People):
grade = ''
def __init__(self, n, a, w, g):
# 調用父類的構函
People.__init__(self, n, a, w)
self.grade = g
# 覆寫父類的方法
def speak(self):
print("%s 說: 我 %d 歲了,我在讀 %d 年級" % (self.name, self.age, self.grade))
# 另一個類,多重繼承之前的準備
class Speaker:
topic = ''
name = ''
def __init__(self, n, t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一個演說家,我演講的主題是 %s" % (self.name, self.topic))
# 多重繼承
class Sample01(Speaker, Student):
a = ''
def __init__(self, n, a, w, g, t):
Student.__init__(self, n, a, w, g)
Speaker.__init__(self, n, t)
test = Sample01("Tim", 25, 80, 4, "Python")
test.speak() # 方法名同,默認調用的是在括號中排前地父類的方法
# 我叫 Tim,我是一個演說家,我演講的主題是 Python
class Sample02(Student, Speaker):
a = ''
def __init__(self, n, a, w, g, t):
Student.__init__(self, n, a, w, g)
Speaker.__init__(self, n, t)
test = Sample02("Tim", 25, 80, 4, "Python")
test.speak() # 方法名同,默認調用的是在括號中排前地父類的方法
# Tim 說: 我 25 歲了,我在讀 4 年級
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
組合
即在類中創建另一個類的實例化對象
class Turtle:
def __init__(self, x):
self.num = x
class Fish:
def __init__(self, x):
self.num = x
class Pool:
def __init__(self, x, y):
self.turtle = Turtle(x)
self.fish = Fish(y)
def print_num(self):
print("水池裏面有烏龜%s只,小魚%s條" % (self.turtle.num, self.fish.num))
p = Pool(2, 3)
p.print_num()
# 水池裏面有烏龜2只,小魚3條
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
類屬性和實例屬性
類屬性:類裏面方法外面定義的變量稱爲類屬性。類屬性所屬於類對象並且多個實例對象之間共享同一個類屬性,說白了就是類屬性所有的通過該類實例化的對象都能共享。
class A():
a = xx #類屬性
def __init__(self):
A.a = xx #使用類屬性可以通過 (類名.類屬性)調用。
實例屬性:實例屬性和具體的某個實例對象有關係,並且一個實例對象和另外一個實例對象是不共享屬性的,說白了實例屬性只能在自己的對象裏面使用,其他的對象不能直接使用,因爲self是誰調用,它的值就屬於該對象。
class 類名():
__init__(self):
self.name = xx #實例屬性
區別
- 類屬性:類外面,可以通過實例對象.類屬性和類名.類屬性進行調用。類裏面,通過self.類屬性和類名.類屬性進行調用。
- 實例屬性 :類外面,可以通過實例對象.實例屬性調用。類裏面,通過self.實例屬性調用。
- 實例屬性就相當於局部變量。出了這個類或者這個類的實例對象,就沒有作用了。
- 類屬性就相當於類裏面的全局變量,可以和這個類的所有實例對象共享。
注意:屬性與方法名相同,屬性會覆蓋方法。
Python 嚴格要求方法需要有實例才能被調用,這種限制其實就是 Python 所謂的綁定概念。
因此沒有類方法和屬性方法的區別。
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
數據屬性
Python 對象的數據屬性通常存儲在名爲.__ dict__
的字典中,我們可以直接訪問__dict__
,或利用 Python 的內置函數vars()
獲取.__ dict__
。
class CC:
def setXY(self, x, y):
self.x = x
self.y = y
def printXY(self):
print(self.x, self.y)
dd = CC()
print(dd.__dict__)
# {}
print(vars(dd))
# {}
print(CC.__dict__)
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000C3473DA048>, 'printXY': <function CC.printXY at 0x000000C3473C4F28>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
dd.setXY(4, 5)
print(dd.__dict__)
# {'x': 4, 'y': 5}
print(vars(CC))
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000632CA9B048>, 'printXY': <function CC.printXY at 0x000000632CA83048>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
print(CC.__dict__)
# {'__module__': '__main__', 'setXY': <function CC.setXY at 0x000000632CA9B048>, 'printXY': <function CC.printXY at 0x000000632CA83048>, '__dict__': <attribute '__dict__' of 'CC' objects>, '__weakref__': <attribute '__weakref__' of 'CC' objects>, '__doc__': None}
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
BIF
issubclass(class, classinfo)
方法用於判斷參數 class 是否是類型參數 classinfo 的子類。
一個類被認爲是其自身的子類。
classinfo
可以是類對象的元組,只要class是其中任何一個候選類的子類,則返回True。
isinstance(object, classinfo)
用於判斷一個對象是否是一個已知的類型
type()
不會認爲子類是一種父類類型,不考慮繼承關係。
isinstance()
會認爲子類是一種父類類型,考慮繼承關係。
如果第一個參數不是對象,則永遠返回False
。
如果第二個參數不是類或者由類對象組成的元組,會拋出一個TypeError
異常。
a = 2
print(isinstance(a, int)) # True
print(isinstance(a, str)) # False
print(isinstance(a, (str, int, list))) # True
class A:
pass
class B(A):
pass
print(isinstance(A(), A)) # True
print(type(A()) == A) # True!!!!!!!!!!!!!!!!!!!!!!!!!!
print(isinstance(B(), A)) # True
print(type(B()) == A) # False!!!!!!!!!!!!!!!!!!!!!!!!!
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
hasattr(object, name)
用於判斷對象是否包含對應的屬性。
getattr(object, name[, default])
用於返回一個對象屬性值,若不存在則返回defalt
值
class A(object):
bar = 1
a = A()
print(getattr(a, 'bar')) # 1
print(getattr(a, 'bar2', 3)) # 3
print(getattr(a, 'bar2'))
# AttributeError: 'A' object has no attribute 'bar2'
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
class A(object):
def set(self, a, b):
x = a
a = b
b = x
print(a, b)
a = A()
c = getattr(a, 'set')
c(a='1', b='2') # 2 1
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580
setattr(object, name, value)
對應函數 getattr()
,用於設置屬性值,該屬性不一定是存在的。
delattr(object, name)
用於刪除屬性。
描述符
class property([fget[, fset[, fdel[, doc]]]]
)用於在新式類中返回屬性值。
fget
– 獲取屬性值的函數
fset
– 設置屬性值的函數
fdel
– 刪除屬性值函數
doc
– 屬性描述信息
class C(object):
def __init__(self):
self.__x = None
def getx(self):
return self.__x
def setx(self, value):
self.__x = value
def delx(self):
del self.__x
x = property(getx, setx, delx, "I'm the 'x' property.")
cc = C()
cc.x = 2
print(cc.x) # 2
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102292580