python基礎(chǔ)之函數(shù)和面向?qū)ο笤斀?/h1>
更新時(shí)間:2022年02月15日 10:26:15 作者:grizzly00
這篇文章主要為大家詳細(xì)介紹了python的函數(shù)和面向?qū)ο?,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
函數(shù)
python中『一切皆對象』, 函數(shù)也不例外.
在之前所學(xué)的C++
或Java
中, 可以發(fā)現(xiàn)函數(shù)的返回值要么為空, 要么是某種數(shù)據(jù)類型, 但是在python
中, 返回值可以是任何對象, 包括函數(shù).
函數(shù)參數(shù)
函數(shù)的參數(shù)種類比較多, 主要有:
1.位置參數(shù) (positional argument
): 就是最常見的x, y等
2默認(rèn)參數(shù) (default argument
): 給定一個(gè)默認(rèn)值, 用戶也可以傳入實(shí)參來調(diào)整.
def func(x, y=3):
print(x+y)
func(1) # 4
func(1, 666) # 667
3.可變參數(shù) (variable argument
): 不限制輸入?yún)?shù)的個(gè)數(shù), 傳入后自動(dòng)保存為元組類型.
1.*args
是可變參數(shù),args
接收的是一個(gè) tuple
def printinfo(arg1, *args):
print(arg1)
print(args, type(args))
printinfo(10) # 僅一個(gè)參數(shù), 沒有屬于args的.
# 10
# () <class 'tuple'>
printinfo(70, 60, 50) # 除arg1位置匹配的, 其他都傳入給可變參數(shù)
# 70
# (60, 50) <class 'tuple'>
4.關(guān)鍵字參數(shù) (keyword argument
): 不限制關(guān)鍵字的個(gè)數(shù)和命名, 傳入后自動(dòng)保存為字典的形式.
1.**kw
是關(guān)鍵字參數(shù),kw
接收的是一個(gè) dict
def printinfo(arg1, *args):
print(arg1)
print(args, type(args))
printinfo(10) # 僅一個(gè)參數(shù), 沒有屬于args的.
# 10
# () <class 'tuple'>
printinfo(70, 60, 50) # 除arg1位置匹配的, 其他都傳入給可變參數(shù)
# 70
# (60, 50) <class 'tuple'>
5.命名關(guān)鍵字參數(shù) (name keyword argument
)
1.命名關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的『參數(shù)名』,也可以提供默認(rèn)值.
2.與關(guān)鍵字參數(shù)不同的是, 關(guān)鍵字參數(shù)的名字和值都是任意的, 后續(xù)再進(jìn)行匹配使用, 而命名關(guān)鍵字則只能接受給定的關(guān)鍵字作為參數(shù).定義命名關(guān)鍵字參數(shù)
3.不要忘了寫分隔符 *
, 否則定義的是位置參數(shù), 命名關(guān)鍵字參數(shù)調(diào)用函數(shù)時(shí)必須給定參數(shù)名.
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, 需要傳入給定關(guān)鍵字
6.參數(shù)組合
在Python
中定義函數(shù)時(shí), 以上這5種參數(shù)都可以使用, d但最多可以使用4種, 并且要注意順序:
1.位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù).
2.位置參數(shù)、默認(rèn)參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù).
變量作用域
在python程序中, 處于不同位置的變量, 有不同的作用域.
- 定義在函數(shù)內(nèi)部的變量擁有局部作用域, 該變量稱為局部變量.
- 定義在函數(shù)外部的變量擁有全局作用域, 該變量稱為全局變量.
- 局部變量只能在其被聲明的函數(shù)內(nèi)部訪問, 而全局變量可以在整個(gè)程序范圍內(nèi)訪問.
需要注意的是:
- 當(dāng)局部變量試圖訪問全局變量時(shí), 一定要在函數(shù)內(nèi)聲明
global
. - 當(dāng)局部變量與全局變量命名沖突時(shí), 程序會(huì)優(yōu)先選擇局部變量.
內(nèi)嵌函數(shù)和閉包
內(nèi)嵌函數(shù)就是在外層函數(shù)內(nèi)定義內(nèi)層函數(shù).
def outer():
print('outer函數(shù)在這被調(diào)用')
def inner():
print('inner函數(shù)在這被調(diào)用')
inner() # 該函數(shù)只能在outer函數(shù)內(nèi)部被調(diào)用
outer()
# outer函數(shù)在這被調(diào)用
# inner函數(shù)在這被調(diào)用
閉包是一個(gè)比較重要的語法結(jié)構(gòu), 結(jié)構(gòu)上與內(nèi)嵌函數(shù)類似, 區(qū)別在于返回值, 閉包的外層函數(shù)返回值是一個(gè)函數(shù).
如果在一個(gè)內(nèi)部函數(shù)里對外層非全局作用域的變量進(jìn)行引用, 那么內(nèi)部函數(shù)就被認(rèn)為是閉包.
通過閉包可以訪問外層非全局作用域的變量, 這個(gè)作用域稱為閉包作用域.
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
注意到上述代碼中, 內(nèi)部函數(shù)FunY
中使用了外部非全局作用域的變量x
.
同樣是, 函數(shù)內(nèi)嵌套的函數(shù)作用域也需要特別注意, 若我們需要修改閉包內(nèi)的變量, 需要使用nonlocal
關(guān)鍵字.
num = 999
def outer():
num = 10
def inner():
nonlocal num # nonlocal關(guān)鍵字聲明
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 表達(dá)式
lambda需要注意的是:
- 匿名函數(shù)沒有
return
, 表達(dá)式本身就是返回值. - 匿名函數(shù)擁有『自己的命名空間』, 不能訪問參數(shù)列表之外或全局變量.
匿名函數(shù)主要適用于函數(shù)式編程(函數(shù)不會(huì)影響函數(shù)之外的內(nèi)容)的一些高階函數(shù)中. 例如map映射和filter過濾, 當(dāng)然也可以在自己自定義函數(shù)中使用.
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]
面向?qū)ο?/h2>
三大特性
面向?qū)ο缶捅仨毩私馊筇匦?
- 封裝: 把客觀事物封裝成抽象的類, 讓數(shù)據(jù)和方法給信任的類或?qū)ο蟛僮? 而隱藏部分信息.
- 繼承: 子類自動(dòng)共享父類的屬性和方法.
- 一般認(rèn)為一個(gè)類是自身的子類;
- 可以使用
issubclass(B, A)
查看B
是否是A
的子類. - python也支持多繼承, 但會(huì)使得類的整體層次復(fù)雜, 所以并不建議使用.
- 多態(tài): 同一個(gè)方法的調(diào)用, 會(huì)由于不同對象而得到不同的結(jié)果.
- 必要條件是
繼承
和方法的重寫
.
類、類對象 和 實(shí)例對象
- 類: 就是指對類的定義
- 類對象: 是在創(chuàng)建類的時(shí)候, 在內(nèi)存開辟的一個(gè)空間, 一個(gè)類只有一個(gè)類對象.
- 實(shí)例對象: 通過實(shí)例化類創(chuàng)建的對象, 可以有多個(gè).
類屬性 和 對象屬性
- 類屬性: 類定義內(nèi), 類方法外定義的變量稱為類屬性, 類屬性屬于類對象, 可以被多個(gè)實(shí)例化對象所共享, 就像
我們都有一個(gè)家, 名字叫中國
一樣. - 對象屬性: 對象屬性和具體創(chuàng)建的對象實(shí)例直接相關(guān), 并且相互之間不共享屬性, 就像
我的老婆只是我的
一樣.
class A():
a = 0 #類屬性
def __init__(self, xx):
A.a = xx #使用類屬性可以通過 (類名.類屬性)調(diào)用。
有一些操作屬性的方法:
- 使用
hasattr(object, name)
來判斷對象是否包含對應(yīng)的屬性或方法. - 使用
getattr(object, name)
來獲取屬性或方法. - 使用
setattr(object, name, value)
來修改屬性值, 或創(chuàng)建新的屬性和值. - 使用
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
私有
私有屬性和方法僅需在定義命名的時(shí)候加上兩個(gè)下劃線"__
"即可.
相對于公有屬性和公有方法來說, 私有屬性和私有方法更加的安全. 從定義上來說, 將需要安全保護(hù)的屬性和方法封裝為私有, 可以阻止外部直接調(diào)用, 而必須使用實(shí)例化對象方法
或類方法
進(jìn)行調(diào)用, 從而提高安全性.
但在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
# 直接訪問則會(huì)報(bào)錯(cuò).
print(counter.__secretCount)
實(shí)例直接使用點(diǎn)就可以增加屬性了, 這點(diǎn)需要注意一下.
class B:
def func(self):
print('調(diào)用func方法')
b = B()
print(b.__dict__) # 查看屬性 {}
b.name = '張三'
b.age = 18
print(b.__dict__) # 查看屬性{'name': '張三', 'age': 18}
b1 = B()
print(b1.__dict__) # 查看屬性 {}
魔法方法
基本的魔法方法
魔法方法基本上是被下劃線包圍的一些特殊方法. 相比于普通的方法, 它能夠在適當(dāng)?shù)臅r(shí)候自動(dòng)調(diào)用. 第一個(gè)參數(shù)一般是cls
『類方法』或者self
『實(shí)例方法』.
__init__(self[, ...])
構(gòu)造器, 當(dāng)一個(gè)實(shí)例被創(chuàng)建的時(shí)候調(diào)用的初始化方法.__new__(cls[, ...])
在一個(gè)對象實(shí)例化的時(shí)候所調(diào)用的第一個(gè)方法, 在調(diào)用__init__
初始化前, 先調(diào)用__new__
.- 需要注意的是,
__new__
的返回值必須為當(dāng)前類的實(shí)例, 否則將不會(huì)調(diào)用__init__
初始化. - 主要是在繼承一些不可變的class(比如
int, str, tuple
)時(shí), 提供一個(gè)自定義該類實(shí)例化過程的途徑.
__del__(self)
析構(gòu)器, 當(dāng)一個(gè)對象將要被系統(tǒng)回收之時(shí)調(diào)用的方法.__str__(self)
: 當(dāng)你打印一個(gè)對象、使用%s
格式化或使用str
強(qiáng)轉(zhuǎn)數(shù)據(jù)類型的時(shí)候,觸發(fā)__str__
.__repr__(self)
是__str__(self)
的備胎, 情況類似, 不過自定義時(shí)往往更加準(zhǔn)確, 主要用于調(diào)試.
算術(shù)運(yùn)算符
普通的計(jì)算在對象中是無法進(jìn)行的, 需要自定義計(jì)算方式.
__add__(self, other)
定義加法的行為: +
__sub__(self, other)
定義減法的行為: -
__mul__(self, other)
定義乘法的行為: *
__truediv__(self, other)
定義真除法的行為: /
__floordiv__(self, other)
定義整數(shù)除法的行為: //
__mod__(self, other)
定義取模算法的行為: %
__divmod__(self, other)
定義當(dāng)被 divmod()
調(diào)用時(shí)的行為
divmod(a, b)
把除數(shù)和余數(shù)運(yùn)算結(jié)果結(jié)合起來,返回一個(gè)包含商和余數(shù)的元組(a // b, a % b)
。
__pow__(self, other[, module])
定義當(dāng)被 power()
調(diào)用或 **
運(yùn)算時(shí)的行為
__lshift__(self, other)
定義按位左移位的行為: <<
__rshift__(self, other)
定義按位右移位的行為: >>
__and__(self, other)
定義按位與操作的行為: &
__xor__(self, other)
定義按位異或操作的行為: ^
__or__(self, other)
定義按位或操作的行為: |
還有對應(yīng)的反運(yùn)算符, 在之前加上r
即可, 例如__rsub__
. 對應(yīng)增量賦值運(yùn)算符, 在之前加上i
即可, 例如__isub__
.
屬性訪問
__getattr__(self, name)
: 定義當(dāng)用戶試圖獲取一個(gè)不存在的屬性時(shí)的行為.
__getattribute__(self, name)
: 定義當(dāng)該類的屬性被訪問時(shí)的行為(先調(diào)用該方法, 查看是否存在該屬性, 若不存在, 接著去調(diào)用__getattr__
).
__setattr__(self, name, value)
: 定義當(dāng)一個(gè)屬性被設(shè)置時(shí)的行為.
__delattr__(self, name)
: 定義當(dāng)一個(gè)屬性被刪除時(shí)的行為.
描述符
描述符就是將某種特殊類型的類的實(shí)例指派給另一個(gè)類的屬性.
__get__(self, instance, owner)
: 用于訪問屬性, 它返回屬性的值.
__set__(self, instance, value)
: 將在屬性分配操作中調(diào)用, 不返回任何內(nèi)容.
__del__(self, instance)
: 控制刪除操作, 不返回任何內(nèi)容.
迭代器和生成器
迭代器
迭代是Python
最強(qiáng)大的功能之一, 是訪問集合元素的一種方式.
- 迭代器是一個(gè)可以記住遍歷的位置的對象.
- 迭代器對象從集合的第一個(gè)元素開始訪問, 直到所有的元素被訪問完結(jié)束.
- 迭代器只能往前不會(huì)后退.
- 字符串, 列表或元組對象都可用于創(chuàng)建迭代器.
迭代器有兩個(gè)基本的方法: iter()
和 next()
:
iter(object)
函數(shù)用來生成迭代器.next(iterator[, default])
返回迭代器的下一個(gè)項(xiàng)目. 在元素為空時(shí)返回默認(rèn)值, 若沒有則會(huì)觸發(fā) StopIteration
異常. 在元組推導(dǎo)式和next中使用過, 不過是下面的『生成器』.
把一個(gè)類作為一個(gè)迭代器使用需要在類中實(shí)現(xiàn)兩個(gè)魔法方法 __iter__()
與 __next__()
.
__iter__(self)
定義當(dāng)?shù)萜髦械脑氐男袨? 返回一個(gè)特殊的迭代器對象, 這個(gè)迭代器對象實(shí)現(xiàn)了 __next__()
方法并通過 StopIteration
異常標(biāo)識迭代的完成.__next__()
返回下一個(gè)迭代器對象. StopIteration
異常用于標(biāo)識迭代的完成,防止出現(xiàn)無限循環(huán)的情況,在 __next__()
方法中我們可以設(shè)置在完成指定循環(huán)次數(shù)后觸發(fā) StopIteration
異常來結(jié)束迭代。
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
的函數(shù)被稱為生成器(generator)。
- 跟普通函數(shù)不同的是, 生成器是一個(gè)返回迭代器的函數(shù), 只能用于迭代操作, 更簡單點(diǎn)理解生成器就是一個(gè)迭代器.
- 在調(diào)用生成器運(yùn)行的過程中, 每次遇到
yield
時(shí)函數(shù)會(huì)暫停并保存當(dāng)前所有的運(yùn)行信息, 返回 yield
的值, 并在下一次執(zhí)行 next()
方法時(shí)從當(dāng)前位置繼續(xù)運(yùn)行. - 調(diào)用一個(gè)生成器函數(shù), 返回的是一個(gè)迭代器對象.
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
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
-
python中使用Celery容聯(lián)云異步發(fā)送驗(yàn)證碼功能
Celery 是一個(gè) 基于python開發(fā)的分布式異步消息任務(wù)隊(duì)列,通過它可以輕松的實(shí)現(xiàn)任務(wù)的異步處理,本文重點(diǎn)給大家介紹使用Celery容聯(lián)云異步發(fā)送驗(yàn)證碼功能,感興趣的朋友一起看看吧 2021-09-09
-
Python之lambda匿名函數(shù)及map和filter的用法
今天小編就為大家分享一篇關(guān)于Python之lambda匿名函數(shù)及map和filter的用法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧 2019-03-03
-
Python基于select實(shí)現(xiàn)的socket服務(wù)器
這篇文章主要介紹了Python基于select實(shí)現(xiàn)的socket服務(wù)器,實(shí)例分析了Python基于select與socket模塊實(shí)現(xiàn)socket通信的相關(guān)技巧,需要的朋友可以參考下 2016-04-04
最新評論
函數(shù)
python中『一切皆對象』, 函數(shù)也不例外.
在之前所學(xué)的C++
或Java
中, 可以發(fā)現(xiàn)函數(shù)的返回值要么為空, 要么是某種數(shù)據(jù)類型, 但是在python
中, 返回值可以是任何對象, 包括函數(shù).
函數(shù)參數(shù)
函數(shù)的參數(shù)種類比較多, 主要有:
1.位置參數(shù) (positional argument
): 就是最常見的x, y等
2默認(rèn)參數(shù) (default argument
): 給定一個(gè)默認(rèn)值, 用戶也可以傳入實(shí)參來調(diào)整.
def func(x, y=3): print(x+y) func(1) # 4 func(1, 666) # 667
3.可變參數(shù) (variable argument
): 不限制輸入?yún)?shù)的個(gè)數(shù), 傳入后自動(dòng)保存為元組類型.
1.*args
是可變參數(shù),args
接收的是一個(gè) tuple
def printinfo(arg1, *args): print(arg1) print(args, type(args)) printinfo(10) # 僅一個(gè)參數(shù), 沒有屬于args的. # 10 # () <class 'tuple'> printinfo(70, 60, 50) # 除arg1位置匹配的, 其他都傳入給可變參數(shù) # 70 # (60, 50) <class 'tuple'>
4.關(guān)鍵字參數(shù) (keyword argument
): 不限制關(guān)鍵字的個(gè)數(shù)和命名, 傳入后自動(dòng)保存為字典的形式.
1.**kw
是關(guān)鍵字參數(shù),kw
接收的是一個(gè) dict
def printinfo(arg1, *args): print(arg1) print(args, type(args)) printinfo(10) # 僅一個(gè)參數(shù), 沒有屬于args的. # 10 # () <class 'tuple'> printinfo(70, 60, 50) # 除arg1位置匹配的, 其他都傳入給可變參數(shù) # 70 # (60, 50) <class 'tuple'>
5.命名關(guān)鍵字參數(shù) (name keyword argument
)
1.命名關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的『參數(shù)名』,也可以提供默認(rèn)值.
2.與關(guān)鍵字參數(shù)不同的是, 關(guān)鍵字參數(shù)的名字和值都是任意的, 后續(xù)再進(jìn)行匹配使用, 而命名關(guān)鍵字則只能接受給定的關(guān)鍵字作為參數(shù).定義命名關(guān)鍵字參數(shù)
3.不要忘了寫分隔符 *
, 否則定義的是位置參數(shù), 命名關(guān)鍵字參數(shù)調(diào)用函數(shù)時(shí)必須給定參數(shù)名.
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, 需要傳入給定關(guān)鍵字
6.參數(shù)組合
在Python
中定義函數(shù)時(shí), 以上這5種參數(shù)都可以使用, d但最多可以使用4種, 并且要注意順序:
1.位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù).
2.位置參數(shù)、默認(rèn)參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù).
變量作用域
在python程序中, 處于不同位置的變量, 有不同的作用域.
- 定義在函數(shù)內(nèi)部的變量擁有局部作用域, 該變量稱為局部變量.
- 定義在函數(shù)外部的變量擁有全局作用域, 該變量稱為全局變量.
- 局部變量只能在其被聲明的函數(shù)內(nèi)部訪問, 而全局變量可以在整個(gè)程序范圍內(nèi)訪問.
需要注意的是:
- 當(dāng)局部變量試圖訪問全局變量時(shí), 一定要在函數(shù)內(nèi)聲明
global
. - 當(dāng)局部變量與全局變量命名沖突時(shí), 程序會(huì)優(yōu)先選擇局部變量.
內(nèi)嵌函數(shù)和閉包
內(nèi)嵌函數(shù)就是在外層函數(shù)內(nèi)定義內(nèi)層函數(shù).
def outer(): print('outer函數(shù)在這被調(diào)用') def inner(): print('inner函數(shù)在這被調(diào)用') inner() # 該函數(shù)只能在outer函數(shù)內(nèi)部被調(diào)用 outer() # outer函數(shù)在這被調(diào)用 # inner函數(shù)在這被調(diào)用
閉包是一個(gè)比較重要的語法結(jié)構(gòu), 結(jié)構(gòu)上與內(nèi)嵌函數(shù)類似, 區(qū)別在于返回值, 閉包的外層函數(shù)返回值是一個(gè)函數(shù).
如果在一個(gè)內(nèi)部函數(shù)里對外層非全局作用域的變量進(jìn)行引用, 那么內(nèi)部函數(shù)就被認(rèn)為是閉包.
通過閉包可以訪問外層非全局作用域的變量, 這個(gè)作用域稱為閉包作用域.
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
注意到上述代碼中, 內(nèi)部函數(shù)
FunY
中使用了外部非全局作用域的變量x
.
同樣是, 函數(shù)內(nèi)嵌套的函數(shù)作用域也需要特別注意, 若我們需要修改閉包內(nèi)的變量, 需要使用nonlocal
關(guān)鍵字.
num = 999 def outer(): num = 10 def inner(): nonlocal num # nonlocal關(guān)鍵字聲明 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 表達(dá)式
lambda需要注意的是:
- 匿名函數(shù)沒有
return
, 表達(dá)式本身就是返回值. - 匿名函數(shù)擁有『自己的命名空間』, 不能訪問參數(shù)列表之外或全局變量.
匿名函數(shù)主要適用于函數(shù)式編程(函數(shù)不會(huì)影響函數(shù)之外的內(nèi)容)的一些高階函數(shù)中. 例如map映射和filter過濾, 當(dāng)然也可以在自己自定義函數(shù)中使用.
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]
面向?qū)ο?/h2>
三大特性
面向?qū)ο缶捅仨毩私馊筇匦?
- 封裝: 把客觀事物封裝成抽象的類, 讓數(shù)據(jù)和方法給信任的類或?qū)ο蟛僮? 而隱藏部分信息.
- 繼承: 子類自動(dòng)共享父類的屬性和方法.
- 一般認(rèn)為一個(gè)類是自身的子類;
- 可以使用
issubclass(B, A)
查看B
是否是A
的子類. - python也支持多繼承, 但會(huì)使得類的整體層次復(fù)雜, 所以并不建議使用.
- 多態(tài): 同一個(gè)方法的調(diào)用, 會(huì)由于不同對象而得到不同的結(jié)果.
- 必要條件是
繼承
和方法的重寫
.
- 必要條件是
類、類對象 和 實(shí)例對象
- 類: 就是指對類的定義
- 類對象: 是在創(chuàng)建類的時(shí)候, 在內(nèi)存開辟的一個(gè)空間, 一個(gè)類只有一個(gè)類對象.
- 實(shí)例對象: 通過實(shí)例化類創(chuàng)建的對象, 可以有多個(gè).
類屬性 和 對象屬性
- 類屬性: 類定義內(nèi), 類方法外定義的變量稱為類屬性, 類屬性屬于類對象, 可以被多個(gè)實(shí)例化對象所共享, 就像
我們都有一個(gè)家, 名字叫中國
一樣. - 對象屬性: 對象屬性和具體創(chuàng)建的對象實(shí)例直接相關(guān), 并且相互之間不共享屬性, 就像
我的老婆只是我的
一樣.
class A(): a = 0 #類屬性 def __init__(self, xx): A.a = xx #使用類屬性可以通過 (類名.類屬性)調(diào)用。
有一些操作屬性的方法:
- 使用
hasattr(object, name)
來判斷對象是否包含對應(yīng)的屬性或方法. - 使用
getattr(object, name)
來獲取屬性或方法. - 使用
setattr(object, name, value)
來修改屬性值, 或創(chuàng)建新的屬性和值. - 使用
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
私有
私有屬性和方法僅需在定義命名的時(shí)候加上兩個(gè)下劃線"__
"即可.
相對于公有屬性和公有方法來說, 私有屬性和私有方法更加的安全. 從定義上來說, 將需要安全保護(hù)的屬性和方法封裝為私有, 可以阻止外部直接調(diào)用, 而必須使用實(shí)例化對象方法
或類方法
進(jìn)行調(diào)用, 從而提高安全性.
但在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 # 直接訪問則會(huì)報(bào)錯(cuò). print(counter.__secretCount)
實(shí)例直接使用點(diǎn)就可以增加屬性了, 這點(diǎn)需要注意一下.
class B: def func(self): print('調(diào)用func方法') b = B() print(b.__dict__) # 查看屬性 {} b.name = '張三' b.age = 18 print(b.__dict__) # 查看屬性{'name': '張三', 'age': 18} b1 = B() print(b1.__dict__) # 查看屬性 {}
魔法方法
基本的魔法方法
魔法方法基本上是被下劃線包圍的一些特殊方法. 相比于普通的方法, 它能夠在適當(dāng)?shù)臅r(shí)候自動(dòng)調(diào)用. 第一個(gè)參數(shù)一般是cls
『類方法』或者self
『實(shí)例方法』.
__init__(self[, ...])
構(gòu)造器, 當(dāng)一個(gè)實(shí)例被創(chuàng)建的時(shí)候調(diào)用的初始化方法.__new__(cls[, ...])
在一個(gè)對象實(shí)例化的時(shí)候所調(diào)用的第一個(gè)方法, 在調(diào)用__init__
初始化前, 先調(diào)用__new__
.- 需要注意的是,
__new__
的返回值必須為當(dāng)前類的實(shí)例, 否則將不會(huì)調(diào)用__init__
初始化. - 主要是在繼承一些不可變的class(比如
int, str, tuple
)時(shí), 提供一個(gè)自定義該類實(shí)例化過程的途徑.
- 需要注意的是,
__del__(self)
析構(gòu)器, 當(dāng)一個(gè)對象將要被系統(tǒng)回收之時(shí)調(diào)用的方法.__str__(self)
: 當(dāng)你打印一個(gè)對象、使用%s
格式化或使用str
強(qiáng)轉(zhuǎn)數(shù)據(jù)類型的時(shí)候,觸發(fā)__str__
.__repr__(self)
是__str__(self)
的備胎, 情況類似, 不過自定義時(shí)往往更加準(zhǔn)確, 主要用于調(diào)試.
算術(shù)運(yùn)算符
普通的計(jì)算在對象中是無法進(jìn)行的, 需要自定義計(jì)算方式.
__add__(self, other)
定義加法的行為: +
__sub__(self, other)
定義減法的行為: -
__mul__(self, other)
定義乘法的行為: *
__truediv__(self, other)
定義真除法的行為: /
__floordiv__(self, other)
定義整數(shù)除法的行為: //
__mod__(self, other)
定義取模算法的行為: %
__divmod__(self, other)
定義當(dāng)被 divmod()
調(diào)用時(shí)的行為
divmod(a, b)
把除數(shù)和余數(shù)運(yùn)算結(jié)果結(jié)合起來,返回一個(gè)包含商和余數(shù)的元組(a // b, a % b)
。
__pow__(self, other[, module])
定義當(dāng)被 power()
調(diào)用或 **
運(yùn)算時(shí)的行為
__lshift__(self, other)
定義按位左移位的行為: <<
__rshift__(self, other)
定義按位右移位的行為: >>
__and__(self, other)
定義按位與操作的行為: &
__xor__(self, other)
定義按位異或操作的行為: ^
__or__(self, other)
定義按位或操作的行為: |
還有對應(yīng)的反運(yùn)算符, 在之前加上r
即可, 例如__rsub__
. 對應(yīng)增量賦值運(yùn)算符, 在之前加上i
即可, 例如__isub__
.
屬性訪問
__getattr__(self, name)
: 定義當(dāng)用戶試圖獲取一個(gè)不存在的屬性時(shí)的行為.
__getattribute__(self, name)
: 定義當(dāng)該類的屬性被訪問時(shí)的行為(先調(diào)用該方法, 查看是否存在該屬性, 若不存在, 接著去調(diào)用__getattr__
).
__setattr__(self, name, value)
: 定義當(dāng)一個(gè)屬性被設(shè)置時(shí)的行為.
__delattr__(self, name)
: 定義當(dāng)一個(gè)屬性被刪除時(shí)的行為.
描述符
描述符就是將某種特殊類型的類的實(shí)例指派給另一個(gè)類的屬性.
__get__(self, instance, owner)
: 用于訪問屬性, 它返回屬性的值.
__set__(self, instance, value)
: 將在屬性分配操作中調(diào)用, 不返回任何內(nèi)容.
__del__(self, instance)
: 控制刪除操作, 不返回任何內(nèi)容.
迭代器和生成器
迭代器
迭代是Python
最強(qiáng)大的功能之一, 是訪問集合元素的一種方式.
- 迭代器是一個(gè)可以記住遍歷的位置的對象.
- 迭代器對象從集合的第一個(gè)元素開始訪問, 直到所有的元素被訪問完結(jié)束.
- 迭代器只能往前不會(huì)后退.
- 字符串, 列表或元組對象都可用于創(chuàng)建迭代器.
迭代器有兩個(gè)基本的方法: iter()
和 next()
:
iter(object)
函數(shù)用來生成迭代器.next(iterator[, default])
返回迭代器的下一個(gè)項(xiàng)目. 在元素為空時(shí)返回默認(rèn)值, 若沒有則會(huì)觸發(fā)StopIteration
異常. 在元組推導(dǎo)式和next中使用過, 不過是下面的『生成器』.
把一個(gè)類作為一個(gè)迭代器使用需要在類中實(shí)現(xiàn)兩個(gè)魔法方法 __iter__()
與 __next__()
.
__iter__(self)
定義當(dāng)?shù)萜髦械脑氐男袨? 返回一個(gè)特殊的迭代器對象, 這個(gè)迭代器對象實(shí)現(xiàn)了__next__()
方法并通過StopIteration
異常標(biāo)識迭代的完成.__next__()
返回下一個(gè)迭代器對象.StopIteration
異常用于標(biāo)識迭代的完成,防止出現(xiàn)無限循環(huán)的情況,在__next__()
方法中我們可以設(shè)置在完成指定循環(huán)次數(shù)后觸發(fā)StopIteration
異常來結(jié)束迭代。
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
的函數(shù)被稱為生成器(generator)。
- 跟普通函數(shù)不同的是, 生成器是一個(gè)返回迭代器的函數(shù), 只能用于迭代操作, 更簡單點(diǎn)理解生成器就是一個(gè)迭代器.
- 在調(diào)用生成器運(yùn)行的過程中, 每次遇到
yield
時(shí)函數(shù)會(huì)暫停并保存當(dāng)前所有的運(yùn)行信息, 返回yield
的值, 并在下一次執(zhí)行next()
方法時(shí)從當(dāng)前位置繼續(xù)運(yùn)行. - 調(diào)用一個(gè)生成器函數(shù), 返回的是一個(gè)迭代器對象.
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
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
python中使用Celery容聯(lián)云異步發(fā)送驗(yàn)證碼功能
Celery 是一個(gè) 基于python開發(fā)的分布式異步消息任務(wù)隊(duì)列,通過它可以輕松的實(shí)現(xiàn)任務(wù)的異步處理,本文重點(diǎn)給大家介紹使用Celery容聯(lián)云異步發(fā)送驗(yàn)證碼功能,感興趣的朋友一起看看吧2021-09-09Python之lambda匿名函數(shù)及map和filter的用法
今天小編就為大家分享一篇關(guān)于Python之lambda匿名函數(shù)及map和filter的用法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03Python基于select實(shí)現(xiàn)的socket服務(wù)器
這篇文章主要介紹了Python基于select實(shí)現(xiàn)的socket服務(wù)器,實(shí)例分析了Python基于select與socket模塊實(shí)現(xiàn)socket通信的相關(guān)技巧,需要的朋友可以參考下2016-04-04