您好,登錄后才能下訂單哦!
這篇文章主要介紹“python函數和面向對象實例分析”,在日常操作中,相信很多人在python函數和面向對象實例分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”python函數和面向對象實例分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
python中『一切皆對象』, 函數也不例外.
在之前所學的C++
或Java
中, 可以發現函數的返回值要么為空, 要么是某種數據類型, 但是在python
中, 返回值可以是任何對象, 包括函數.
函數的參數種類比較多, 主要有:
1.位置參數 (positional argument
): 就是最常見的x, y等
2默認參數 (default argument
): 給定一個默認值, 用戶也可以傳入實參來調整.
def func(x, y=3): print(x+y) func(1) # 4 func(1, 666) # 667
3.可變參數 (variable argument
): 不限制輸入參數的個數, 傳入后自動保存為元組類型.
1.*args
是可變參數,args
接收的是一個 tuple
def printinfo(arg1, *args): print(arg1) print(args, type(args)) printinfo(10) # 僅一個參數, 沒有屬于args的. # 10 # () <class 'tuple'> printinfo(70, 60, 50) # 除arg1位置匹配的, 其他都傳入給可變參數 # 70 # (60, 50) <class 'tuple'>
4.關鍵字參數 (keyword argument
): 不限制關鍵字的個數和命名, 傳入后自動保存為字典的形式.
1.**kw
是關鍵字參數,kw
接收的是一個 dict
def printinfo(arg1, *args): print(arg1) print(args, type(args)) printinfo(10) # 僅一個參數, 沒有屬于args的. # 10 # () <class 'tuple'> printinfo(70, 60, 50) # 除arg1位置匹配的, 其他都傳入給可變參數 # 70 # (60, 50) <class 'tuple'>
5.命名關鍵字參數 (name keyword argument
)
1.命名關鍵字參數是為了限制調用者可以傳入的『參數名』,也可以提供默認值.
2.與關鍵字參數不同的是, 關鍵字參數的名字和值都是任意的, 后續再進行匹配使用, 而命名關鍵字則只能接受給定的關鍵字作為參數.定義命名關鍵字參數
3.不要忘了寫分隔符 *
, 否則定義的是位置參數, 命名關鍵字參數調用函數時必須給定參數名.
def person(name, *, age, height=1.90): print(f'{name}今年{age}歲, 身高{height:.2f}m') person('張三', age=18, height=1.80) # 張三今年18歲, 身高1.80m person('李四', age=18) # 李四今年18歲, 身高1.90m person('王五') # TypeError, 需要傳入給定關鍵字
6.參數組合
在Python
中定義函數時, 以上這5種參數都可以使用, d但最多可以使用4種, 并且要注意順序:
1.位置參數、默認參數、可變參數和關鍵字參數.
2.位置參數、默認參數、命名關鍵字參數和關鍵字參數.
在python程序中, 處于不同位置的變量, 有不同的作用域.
定義在函數內部的變量擁有局部作用域, 該變量稱為局部變量.
定義在函數外部的變量擁有全局作用域, 該變量稱為全局變量.
局部變量只能在其被聲明的函數內部訪問, 而全局變量可以在整個程序范圍內訪問.
需要注意的是:
當局部變量試圖訪問全局變量時, 一定要在函數內聲明global
.
當局部變量與全局變量命名沖突時, 程序會優先選擇局部變量.
內嵌函數就是在外層函數內定義內層函數.
def outer(): print('outer函數在這被調用') def inner(): print('inner函數在這被調用') inner() # 該函數只能在outer函數內部被調用 outer() # outer函數在這被調用 # inner函數在這被調用
閉包是一個比較重要的語法結構, 結構上與內嵌函數類似, 區別在于返回值, 閉包的外層函數返回值是一個函數.
如果在一個內部函數里對外層非全局作用域的變量進行引用, 那么內部函數就被認為是閉包.
通過閉包可以訪問外層非全局作用域的變量, 這個作用域稱為閉包作用域.
def funX(x): def funY(y): print('使用funY(y)') return x * y return funY i = funX(8) print(type(i)) # <class 'function'> print(i(5)) # 40
注意到上述代碼中, 內部函數
FunY
中使用了外部非全局作用域的變量x
.
同樣是, 函數內嵌套的函數作用域也需要特別注意, 若我們需要修改閉包內的變量, 需要使用nonlocal
關鍵字.
num = 999 def outer(): num = 10 def inner(): nonlocal num # nonlocal關鍵字聲明 num = 100 print(f'inner中num = {num}') inner() print(f'outer中num = {num}') outer() # inner中num = 100 # outer中num = 100 print(f'全局中num = {num}') # 全局中num = 999
lambda需要注意的是:
匿名函數沒有return
, 表達式本身就是返回值.
匿名函數擁有『自己的命名空間』, 不能訪問參數列表之外或全局變量.
匿名函數主要適用于函數式編程(函數不會影響函數之外的內容)的一些高階函數中. 例如map映射和filter過濾, 當然也可以在自己自定義函數中使用.
odd = lambda x: x % 2 == 1 templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9]) print(list(templist)) # [1, 3, 5, 7, 9] m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5]) print(list(m1)) # [1, 4, 9, 16, 25]
面向對象就必須了解三大特性:
封裝: 把客觀事物封裝成抽象的類, 讓數據和方法給信任的類或對象操作, 而隱藏部分信息.
繼承: 子類自動共享父類的屬性和方法.
一般認為一個類是自身的子類;
可以使用issubclass(B, A)
查看B
是否是A
的子類.
python也支持多繼承, 但會使得類的整體層次復雜, 所以并不建議使用.
多態: 同一個方法的調用, 會由于不同對象而得到不同的結果.
必要條件是繼承
和方法的重寫
.
類: 就是指對類的定義
類對象: 是在創建類的時候, 在內存開辟的一個空間, 一個類只有一個類對象.
實例對象: 通過實例化類創建的對象, 可以有多個.
類屬性: 類定義內, 類方法外定義的變量稱為類屬性, 類屬性屬于類對象, 可以被多個實例化對象所共享, 就像我們都有一個家, 名字叫中國
一樣.
對象屬性: 對象屬性和具體創建的對象實例直接相關, 并且相互之間不共享屬性, 就像我的老婆只是我的
一樣.
class A(): a = 0 #類屬性 def __init__(self, xx): A.a = xx #使用類屬性可以通過 (類名.類屬性)調用。
有一些操作屬性的方法:
使用hasattr(object, name)
來判斷對象是否包含對應的屬性或方法.
使用getattr(object, name)
來獲取屬性或方法.
使用setattr(object, name, value)
來修改屬性值, 或創建新的屬性和值.
使用delattr(object, name)
來刪除屬性.
class A(object): name = '張三' def set(self, a, b): x = a a = b b = x print(a, b) a = A() print(hasattr(a, 'name')) # 判斷是否有name屬性 True print(hasattr(a, 'set')) # 判斷是否有set方法 True x = getattr(a, 'name') # 獲取屬性值 print(x) # 張三 c = getattr(a, 'set') # 獲取方法 c(a='1', b='2') # 2 1
私有屬性和方法僅需在定義命名的時候加上兩個下劃線"__
"即可.
相對于公有屬性和公有方法來說, 私有屬性和私有方法更加的安全. 從定義上來說, 將需要安全保護的屬性和方法封裝為私有, 可以阻止外部直接調用, 而必須使用實例化對象方法
或類方法
進行調用, 從而提高安全性.
但在python中的私有是『偽私有』, 即可以使用類名, 通過 object._className__attrName
訪問私有屬性,用 object._className__func()
訪問私有方法.
class JustCounter: __secretCount = 0 # 私有變量 publicCount = 0 # 公開變量 def count(self): self.__secretCount += 1 self.publicCount += 1 print(self.__secretCount) counter = JustCounter() counter.count() # 1 print(counter.publicCount) # 1 # 特殊方法依舊可以訪問 print(counter._JustCounter__secretCount) # 1 # 直接訪問則會報錯. print(counter.__secretCount)
實例直接使用點就可以增加屬性了, 這點需要注意一下.
class B: def func(self): print('調用func方法') b = B() print(b.__dict__) # 查看屬性 {} b.name = '張三' b.age = 18 print(b.__dict__) # 查看屬性{'name': '張三', 'age': 18} b1 = B() print(b1.__dict__) # 查看屬性 {}
魔法方法基本上是被下劃線包圍的一些特殊方法. 相比于普通的方法, 它能夠在適當的時候自動調用. 第一個參數一般是cls
『類方法』或者self
『實例方法』.
__init__(self[, ...])
構造器, 當一個實例被創建的時候調用的初始化方法.
__new__(cls[, ...])
在一個對象實例化的時候所調用的第一個方法, 在調用__init__
初始化前, 先調用__new__
.
需要注意的是, __new__
的返回值必須為當前類的實例, 否則將不會調用__init__
初始化.
主要是在繼承一些不可變的class(比如int, str, tuple
)時, 提供一個自定義該類實例化過程的途徑.
__del__(self)
析構器, 當一個對象將要被系統回收之時調用的方法.
__str__(self)
: 當你打印一個對象、使用%s
格式化或使用str
強轉數據類型的時候,觸發__str__
.
__repr__(self)
是__str__(self)
的備胎, 情況類似, 不過自定義時往往更加準確, 主要用于調試.
普通的計算在對象中是無法進行的, 需要自定義計算方式.
__add__(self, other)
定義加法的行為: +
__sub__(self, other)
定義減法的行為: -
__mul__(self, other)
定義乘法的行為: *
__truediv__(self, other)
定義真除法的行為: /
__floordiv__(self, other)
定義整數除法的行為: //
__mod__(self, other)
定義取模算法的行為: %
__divmod__(self, other)
定義當被 divmod()
調用時的行為
divmod(a, b)
把除數和余數運算結果結合起來,返回一個包含商和余數的元組(a // b, a % b)
。
__pow__(self, other[, module])
定義當被 power()
調用或 **
運算時的行為
__lshift__(self, other)
定義按位左移位的行為: <<
__rshift__(self, other)
定義按位右移位的行為: >>
__and__(self, other)
定義按位與操作的行為: &
__xor__(self, other)
定義按位異或操作的行為: ^
__or__(self, other)
定義按位或操作的行為: |
還有對應的反運算符, 在之前加上r
即可, 例如__rsub__
. 對應增量賦值運算符, 在之前加上i
即可, 例如__isub__
.
__getattr__(self, name)
: 定義當用戶試圖獲取一個不存在的屬性時的行為.
__getattribute__(self, name)
: 定義當該類的屬性被訪問時的行為(先調用該方法, 查看是否存在該屬性, 若不存在, 接著去調用__getattr__
).
__setattr__(self, name, value)
: 定義當一個屬性被設置時的行為.
__delattr__(self, name)
: 定義當一個屬性被刪除時的行為.
描述符就是將某種特殊類型的類的實例指派給另一個類的屬性.
__get__(self, instance, owner)
: 用于訪問屬性, 它返回屬性的值.
__set__(self, instance, value)
: 將在屬性分配操作中調用, 不返回任何內容.
__del__(self, instance)
: 控制刪除操作, 不返回任何內容.
迭代是Python
最強大的功能之一, 是訪問集合元素的一種方式.
迭代器是一個可以記住遍歷的位置的對象.
迭代器對象從集合的第一個元素開始訪問, 直到所有的元素被訪問完結束.
迭代器只能往前不會后退.
字符串, 列表或元組對象都可用于創建迭代器.
迭代器有兩個基本的方法: iter()
和 next()
:
iter(object)
函數用來生成迭代器.
next(iterator[, default])
返回迭代器的下一個項目. 在元素為空時返回默認值, 若沒有則會觸發 StopIteration
異常. 在元組推導式和next中使用過, 不過是下面的『生成器』.
把一個類作為一個迭代器使用需要在類中實現兩個魔法方法 __iter__()
與 __next__()
.
__iter__(self)
定義當迭代容器中的元素的行為, 返回一個特殊的迭代器對象, 這個迭代器對象實現了 __next__()
方法并通過 StopIteration
異常標識迭代的完成.
__next__()
返回下一個迭代器對象.
StopIteration
異常用于標識迭代的完成,防止出現無限循環的情況,在 __next__()
方法中我們可以設置在完成指定循環次數后觸發 StopIteration
異常來結束迭代。
class Fibs: def __init__(self, n=10): self.a = 0 self.b = 1 self.n = n def __iter__(self): return self def __next__(self): self.a, self.b = self.b, self.a + self.b if self.a > self.n: raise StopIteration return self.a fibs = Fibs(100) for each in fibs: print(each, end=' ') # 1 1 2 3 5 8 13 21 34 55 89
在 Python 中,使用了 yield
的函數被稱為生成器(generator)。
跟普通函數不同的是, 生成器是一個返回迭代器的函數, 只能用于迭代操作, 更簡單點理解生成器就是一個迭代器.
在調用生成器運行的過程中, 每次遇到 yield
時函數會暫停并保存當前所有的運行信息, 返回 yield
的值, 并在下一次執行 next()
方法時從當前位置繼續運行.
調用一個生成器函數, 返回的是一個迭代器對象.
def libs(n): a = 0 b = 1 while True: a, b = b, a + b if a > n: return yield a for each in libs(100): print(each, end=' ') # 1 1 2 3 5 8 13 21 34 55 89
到此,關于“python函數和面向對象實例分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。