日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

阿里云天池 Python训练营Task3: Python基础进阶:从函数到高级魔法方法 学习笔记

發布時間:2023/11/30 python 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里云天池 Python训练营Task3: Python基础进阶:从函数到高级魔法方法 学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本學習筆記為阿里云天池龍珠計劃Python訓練營的學習內容,學習鏈接為:https://tianchi.aliyun.com/specials/promotion/aicamppython?spm=5176.22758685.J_6770933040.1.6f103da1tESyzu

目錄

一、學習知識點概要

二、學習內容

I.函數

1.定義自己的函數

2.函數文檔

3.函數參數

4.變量作用域

II.Lambda-表達式

1.定義

2.匿名函數的運用

III.類與對象

1.定義自己的類

2.self

?3.類的構造函數

4.公有和私有

5.類的繼承與多態

6.組合

7.類對象和實例對象

8.綁定

9.相關的內置函數

IV.魔法方法

1.基本的魔法方法

2.算術運算符

3.反算術運算符

4.增量賦值運算符

5.一元運算符

6.屬性訪問

7.描述符

8.定制序列

9.迭代器

三、學習問題與解答

四、學習思考與總結


一、學習知識點概要

本次學習的主要知識有:

  • 函數
  • Lambda-表達式
  • 類與對象
  • 魔法方法

二、學習內容

I.函數

我在之前的文章中把函數稱為方法,其實就是封裝在一起的能夠完成一些操作的代碼塊。和其他語言相同,Python不知有許許多多內置的函數,也能夠定義自己的函數。和其他語言有些不同的是,Python中的函數也是對象,其他函數的返回值也可以是一個函數,進而去構造一些高階的函數。

1.定義自己的函數

在Python中定義自己的函數的語法結構為:

def 函數名 (參數):"函數文檔字符串"函數體return [返回值]
  • 定義函數時以def關鍵詞為開頭,后面為函數名和用小括號括起來的參數,參數可以不止一個
  • 函數執行的是冒號之后的代碼
  • return [返回值]結束函數,中括號[]里面可以填寫返回值返回給函數,返回值也可以是一個表達式。如果不帶表達式則默認返回None

例:

def mean(x):"求序列的均值"return [sum(x)/len(x)] #此處返回的是一個列表a=list(range(4,15)) print(a) #[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] print('a的均值為:',mean(a)) #a的均值為: [9.0]

2.函數文檔

函數文檔是在函數定義中,冒號下一行的字符串,用于解釋函數的用法。在命令窗口中準備使用函數時編譯器會顯示該函數的函數文檔。可以用魔法方法function.__doc__返回函數的函數文檔,也可以用help(functionname)的方式查看到函數名為functionname的函數的函數文檔。

例:

def mean(x):"求序列的均值"return [sum(x)/len(x)]print(mean.__doc__)#'求序列的均值' help(mean)#Help on function mean in module __main__:#mean(x)# 求序列的均值

3.函數參數

Python 的函數具有非常靈活多樣的參數形態,既可以實現簡單的調用,又可以傳入非常復雜的參數。從簡到繁的參數形態如下:

  • 位置參數 (positional argument)
  • 默認參數 (default argument)
  • 可變參數 (variable argument)
  • 關鍵字參數 (keyword argument)
  • 命名關鍵字參數 (name keyword argument)
  • 參數組合

(1)位置參數

定義函數時直接放在函數形參表中,沒有任何操作符的參數。這種參數在調用函數時,位置要固定,除非調用時寫出參數名進行賦值。

(2)默認參數

定義函數時在形參表中完成賦值的參數,這類參數稱為默認參數。若調用函數時傳入了參數,則使用傳入的參數值;如果沒有傳入參數值,則使用默認的參數值。

注:定義函數時默認參數一定要放在位置參數的后面

def printinfo(name, age=8): #name是位置參數,age是默認參數print('Name:{0},Age:{1}'.format(name, age))printinfo('江總',20) #Name:江總,Age:20 printinfo('小王') #Name:小王,Age:8

(3)可變參數

可變參數意為可傳入的參數的個數是可變的,為任意個

  • 在形參表中寫入 *vararg 表示vararg是可變參數
  • 傳入到vararg里的參數會被打包成元組
  • 定義時要將可變參數放到位置參數的后面,否則在調用時會因無法給位置參數傳值而報錯

(4)關鍵字參數

關鍵字參數也可以傳入任意個

  • 在形參表中寫入 **keyarg 表示keyarg是關鍵字參數
  • 傳入到keyarg里的參數會被打包成字典
  • 調用函數給關鍵字參數傳值時以類似?function(…… ,key1=value1,key2=value2,……)賦值的方式將傳入關鍵字參數的鍵值對打包

(5)命名關鍵字參數

由于傳入關鍵字參數時,用戶傳入的鍵值對內容不受限制,如果要限制傳入的關鍵字的名字可以用命名關鍵字參數

  • 在形參表中輸入 *, 分隔符,會將分隔符后面的參數都視為命名關鍵字參數
  • 調用函數時,必須要寫出命名關鍵字參數的參數名,否則會報錯
  • 命名關鍵字參數可以有默認值

例:例程來源:https://blog.51cto.com/u_11317783/1953276

def person(name, age, **kw):if 'city' in kw:#關鍵字參數kw中是否有city參數passif 'job' in kw:#關鍵字參數kw中是否有job參數passprint('name:', name, 'age:', age, 'other:', kw)#調用者仍可以傳入不受限制的關鍵字參數 person('Jack', 24, city='Beijing', addr='朝陽', zipcode=123456) # 如果要限制關鍵字參數的名字,就可以用命名關鍵字參數,例如,只接收city和job作為關鍵字參數def person(name, age, *, city, job):print(name, age, city, job) # 和關鍵字參數**kw不同,命名關鍵字參數需要一個特殊分隔符*,*后面的參數被視為命名關鍵字參數 # 調用方式如下 person('Jack', 24, city='Beijing', job='Engineer')

(6)參數組合

定義函數時可以使用以上5種參數的任意組合,只要符合相關規定即可。但建議不要用太多的參數,否則可能會導致函數代碼的可讀性降低。

4.變量作用域

與其他熱門語言相同,Python中的變量可以分為局部變量和全局變量

  • 定義在函數內部的變量擁有局部作用域,該變量稱為局部變量
  • 定義在函數外部的變量擁有全局作用域,該變量稱為全局變量
  • 局部變量只能在其被聲明的函數內部訪問,而全局變量可以在整個程序范圍內訪問
  • 若內部作用域想修改外部作用域的變量時,需要用global或nonlocal關鍵字,例:
num = 1def fun1():global num # 需要使用 global 關鍵字聲明print(num) # 1num = 123print(num) # 123fun1() print(num) # 123
  • 函數內部可以調用其他函數,稱函數的嵌套

(1)閉包

  • 是函數式編程的一個重要的語法結構,是一種特殊的內嵌函數。
  • 如果在一個內部函數里對外層非全局作用域的變量進行引用,那么內部函數就被認為是閉包。
  • 通過閉包可以訪問外層非全局作用域的變量,這個作用域稱為?閉包作用域
  • 閉包的返回值通常是函數

例:

def make_counter(init):counter = [init]def inc(): counter[0] += 1def dec(): counter[0] -= 1def get(): return counter[0]def reset(): counter[0] = initreturn inc, dec, get, resetinc, dec, get, reset = make_counter(0) #內部的inc,dec,get,reset都是閉包的,可以訪問counter inc() #外面的inc,dec,get,reset由于獲取的是函數make_counter inc() #返回的內部的四個inc,dec,get,reset, inc() #外部的inc,dec,get,reset函數依然可以對局部變量counter print(get()) # 3 #進行操作 dec() print(get()) # 2 reset() print(get()) # 0

global關鍵字聲明的是全局變量,如果要在函數里的函數的局部變量的作用域,可用nonlocal關鍵字。

定義函數時,函數體里面還定義了函數,相當于有兩層函數,內層的函數是閉包的,可以訪問外層函數的變量,但如果內層函數出現了和外層函數同名的變量(假如稱為x)時,內層函數內的代碼會用內層函數的同名變量,這表明在兩個函數的作用域里有兩個不同的x。如果想在內部函數修改外層的變量,則需要在內部函數的變量聲明前加上nonlocal關鍵字,表明內外函數中的這個同名變量是同一個。例:

def outer():num = 10def inner():nonlocal num # nonlocal關鍵字聲明,表明inner內部的num和outer的num是同一個num = 100print(num)inner()print(num)outer()# 100 # 100

(2)遞歸

函數在內部調用自己,稱這個函數為遞歸函數。遞歸是一種重要的操作。例:

# 利用循環 n = 5 for k in range(1, 5):n = n * k print(n) # 120# 利用遞歸 def factorial(n):if n == 1:return 1return n * factorial(n - 1)print(factorial(5)) # 120

?加入包sys,用sys.setrecursionlimit(n)可以設置遞歸的最大次數為n,默認是1000次

II.Lambda-表達式

1.定義

lambda關鍵詞用于定義匿名的函數,匿名函數沒有函數名,語法結構為:

lambda argument_list: expression
  • argument_list為形參表,lambda定義的匿名函數和def定義的函數所用參數相同,但是不用小括號括起來
  • expression為表達式,相當于函數的返回值
  • expression中沒有return語句,因為expression本身就是返回值
  • 匿名函數有自己的命名空間,匿名函數內部不能訪問形參表之外和全局命名空間里的參數

例:

def sqr(x):return x ** 2print(sqr) # <function sqr at 0x000000BABD3A4400>y = [sqr(x) for x in range(10)] #運用def定義的普通函數 print(y) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]lbd_sqr = lambda x: x ** 2 print(lbd_sqr) # <function <lambda> at 0x000000BABB6AC1E0>y = [lbd_sqr(x) for x in range(10)] #運用lambda定義的匿名函數 print(y) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]sumary = lambda arg1, arg2: arg1 + arg2 print(sumary(10, 20)) # 30func = lambda *args: sum(args) print(func(1, 2, 3, 4, 5)) # 15

2.匿名函數的運用

匿名函數常常應用于高階函數中,有兩種運用方式:

  • 參數是函數
  • 返回值是函數

例如Python內置的filter(function,iterable)函數和map(function,*iterable)函數中,都有函數作為參數,如果用先用def定義一個常常會有些麻煩,但如果用lambda定義的匿名函數就會簡潔不少。

odd = lambda x: x % 2 == 1 #filter()過濾序列,過濾掉不符合條件的templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9]) #元素,返回一個迭代器對象,如果要轉換為列 print(list(templist)) #表,可以使用list() 來轉換 # [1, 3, 5, 7, 9]m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5]) #map()根據提供的函數對指定序列做映射 print(list(m1)) # [1, 4, 9, 16, 25]m2 = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]) print(list(m2)) # [3, 7, 11, 15, 19]

III.類與對象

與C++和Java類似,Python也可以定義自己的類。類是對象的模板,對象是類的實例,類中包含屬性和方法(函數)。

1.定義自己的類

我們可以用關鍵字class定義類,關鍵字后面跟類名和冒號,以及類的內容,Python中的類名以大寫字母開頭。例:

class Turtle: # 屬性color = 'green'weight = 10legs = 4shell = Truemouth = '大嘴'# 方法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__) # Turtlett.climb() # 我正在很努力的向前爬...tt.run() # 我正在飛快的向前跑...tt.bite() # 咬死你咬死你!!# Python類也是對象。它們是type的實例 print(type(Turtle)) # <class 'type'>

2.self

Python 中的 self 相當于 C++和Java中的 this 指針。

例:

class Ball:def setName(self, name):self.name = namedef 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,該死的,誰踢我...

?3.類的構造函數

類的構造函數是一種魔法方法,這個魔法方法為__init__(self[,param1,param2…])

Python中的構造函數可以自己定義,但是函數名必須是__init__(self[,param1,param2…])。在類外給類實例化(產生對象)時會自動調用,調用方法是? 類名(參數),參數是__init__()中除self之外的參數。

在定義子類的構造函數時應調用父類的構造函數。如果不調用父類的構造函數,可能會因子類的構造函數覆蓋了父類的構造函數而導致從父類繼承過來的屬性不是自己想要的值。當然,你也可以通過在子類的構造函數里給所有屬性賦值來避免這種情況,但是這樣在類的屬性較多時就會比較繁瑣了。

例子可見下文“類的繼承”部分

4.公有和私有

在 Python 中定義私有變量只需要在變量名或函數名前加上“__”兩個下劃線,那么這個函數或變量就會為私有的了。

其余的與C++和Java中的公有私有類似,此處不作贅述。但是要提的是Python中的私有是偽私有,只要用以下形式仍然可以在類外直接訪問或調用對象的私有屬性或私有方法。

對象._類名__私有屬性 #只需在對象的.和私有數據或方法的雙下劃線__ 對象._類名__私有方法 #之間插入下劃線 _ 加上類名即可

5.類的繼承與多態

定義的類可以用以下語法形式繼承父類:

class 子類名(父類名1,父類名2,……,父類名n):類的實現

子類可以繼承父類的數據和函數。子類必須與派生類定義在一個作用域內。除了類,還可以用表達式,基類定義在另一個模塊中時這一點非常有用。

與Java類似,子類可以重寫父類的函數。但是子類在重寫構造函數時,由于構造函數名不能變化,子類的構造函數就會覆蓋父類的構造函數,這樣可能會出現以下狀況:

import randomclass Fish:def __init__(self):self.x = random.randint(0, 10)self.y = random.randint(0, 10)def move(self):self.x -= 1print("我的位置", self.x, self.y)class GoldFish(Fish): # 金魚passclass Carp(Fish): # 鯉魚passclass Salmon(Fish): # 三文魚passclass Shark(Fish): # 鯊魚def __init__(self):self.hungry = Truedef eat(self):if self.hungry:print("吃貨的夢想就是天天有得吃!")self.hungry = Falseelse:print("太撐了,吃不下了!")self.hungry = Trueg = GoldFish() g.move() # 我的位置 9 4 s = Shark() s.eat() # 吃貨的夢想就是天天有得吃! s.move() # AttributeError: 'Shark' object has no attribute 'x' ''' Shark類的構造函數沒有調用父類Fish的構造函數 導致對象s在實例化時沒有x和y兩個屬性 從而在調用move()函數時訪問x和y就會出錯 '''

?要在子類的構造函數中調用父類的構造函數,可以有以下兩種方法:

class Shark(Fish): # 鯊魚def __init__(self):Fish.__init__(self) #調用未綁定的父類方法Fish.__init__(self)self.hungry = Truedef eat(self):if self.hungry:print("吃貨的夢想就是天天有得吃!")self.hungry = Falseelse:print("太撐了,吃不下了!")self.hungry = True'''或是用以下方法''' class Shark(Fish): # 鯊魚def __init__(self):super().__init__() #用super函數super().__init__()self.hungry = Truedef eat(self):if self.hungry:print("吃貨的夢想就是天天有得吃!")self.hungry = Falseelse:print("太撐了,吃不下了!")self.hungry = True

?其中super函數和Java中的super關鍵字類似,但是在Python的子類中用super()來表示父類的對象。

在多繼承時需要注意圓括號中父類的順序,若是父類中有相同的函數名,而在子類使用時未指定,Python 從左至右搜索,即函數在子類中未找到時,從左到右查找父類中是否包含該函數。

與Java類似,子類也可以通過重寫父類的函數,再通過用子類的構造方法構造父類的對象來實現多態。Java中稱用子類構造方法構造的父類對象為上轉型對象,調用同名的函數時會調用子類中的,但是子類有而父類中沒有的屬性和函數會丟失。

多態:不同對象對同一方法響應不同的行動

例:

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()是Pig類的構造函數 # pig is walking

6.組合

即其他類的對象可以成為另一個類的屬性,例:

class Turtle:def __init__(self, x):self.num = xclass Fish:def __init__(self, x):self.num = xclass 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條

7.類對象和實例對象

  • 在Python中“萬物皆對象”,所以我們創建的類也是一個對象,也在內存中開辟了一塊空間,這種對象叫類對象,類對象只能有一個。
  • 通過實例化類創建的對象稱為實例對象,實例對象可以有多個。

類屬性和實例屬性:

類屬性和實例屬性的說法和Java類似,就是靜態屬性和非靜態屬性的區別,但是Python中的類屬性和實例屬性的聲明不一樣。

  • 在類里面方法外聲明的屬性是類屬性,需要賦值,所有實例對象都可以訪問且共享。
  • 實例屬性是和具體的實例有關,并且一個實例對象和另外一個實例對象是不共享屬性的,說白了實例屬性只能在自己的對象里面使用,其他的對象不能直接使用。可以通過類內的函數或類外賦值創建。
  • 注:在類外賦值創建實例屬性時,如果屬性和函數同名,屬性會覆蓋函數。

8.綁定

Python 嚴格要求方法需要有實例才能被調用,這種限制其實就是 Python 所謂的綁定概念。

Python 對象的數據屬性通常存儲在名為 .__dict__的字典中,我們可以直接訪問 .__dict__ ,或者利用 Python 的內置函數 vars()獲取 .__dict__ 。

9.相關的內置函數

  • issubclass(class,classinfo)? 方法用于判斷參數 class 是否是類型參數 classinfo 的子類
  • 一個類被認為是其自身的子類
  • classinfo?可以是類對象的元組,只要class是其中任何一個候選類的子類,則返回True

?

  • isinstance(object,classinfo)? 方法用于判斷一個對象是否是classinfo的對象,類似type()
  • type()不會認為子類是一種父類類型,不考慮繼承關系
  • isinstance()會認為子類是一種父類類型,考慮繼承關系
  • 如果第一個參數不是對象,則永遠返回False
  • 如果第二個參數不是類或者由類對象組成的元組,會拋出一個TypeError異常

?

  • hasattr(object,name)? 用于判斷對象是否包含對應的屬性
  • getattr(object,name[,default])? 用于返回一個對象屬性值
  • setattr(object,name,value)對應 getattr(),用于設置屬性值,該屬性不一定是存在的
  • delattr(object,name)? 用于刪除屬性

?

  • class property([fget[,fset[,fdel[,doc]]]])??于在新式類中返回屬性值
  • fget? ? ? ? ? ?獲取屬性值的函數
  • fset? ? ? ? ? ?設置屬性值的函數
  • fdel? ? ? ? ? ?刪除屬性值函數
  • doc? ? ? ? ? ?屬性描述信息

IV.魔法方法

Python的魔法方法是一些特殊的方法,又叫魔術方法,例如上文提到的:__init__()。魔法方法是面向對象的 Python 的一切,有著強大的作用。魔法方法有以下特點:

  • 魔法方法總是被雙下劃線包圍
  • 魔法方法總是能夠在適當的時候被自動調用

魔法方法的第一個參數應為 cls (類方法)? 或者 self(實例方法)。cls代表一個類名稱,self代表一個實例對象的名稱。

1.基本的魔法方法

  • __init__(self[,……]) 構造器,即各個類的構造方法,當一個實例被創建的時候調用的初始化方法。
  • __new__(cls[,……])?在一個對象實例化的時候所調用的第一個方法,系統會先調用__new__再調用__init__。
  • 注:__new__()至少要有一個參數cls,代表要實例化的類,此參數在實例化時由 Python 解釋器自動提供,后面的參數直接傳遞給__init__()
  • 注:__new__()對當前類進行了實例化,即產生了一個對象,再將對象返回,傳給__init__中的self。但是__new__返回的實例必須是當前類的實例才會繼續執行__init__。也就是說,如果通過在類中定義了__new__(),使得__new__返回的不是當前類的對象,那當前類中的__init__是不會被調用的,即使返回的是父類的實例也不行。
  • 例:
class A(object):def __init__(self, value):print("into A __init__")self.value = valuedef __new__(cls, *args, **kwargs):print("into A __new__")print(cls)return object.__new__(cls)class B(A):def __init__(self, value):print("into B __init__")self.value = valuedef __new__(cls, *args, **kwargs):print("into B __new__")print(cls)return super().__new__(A, *args, **kwargs) #返回的__new__中的cls參數為A類b = B(10)# 結果: # into B __new__ # <class '__main__.B'> # into A __new__ # <class '__main__.A'>
  • __new__()方法主要是當你繼承一些不可變的 class 時(如:int , str ,tuple), 提供給你一個自定義這些類的實例化過程的途徑。
  • __del__(self) 析構器,相當于C++中的析構函數,當一個對象將要被系統回收之時調用的方法。在類中也可以自己定義__del__()的內容,與C++相似。
  • __str__(self) 當我們打印(print)一個對象的時候、當你使用%s格式化的時候、str()強轉數據類型的時候會調用。
  • __repr__(self)? __repr__是__str__的備用函數,如果沒有實現__str__的時候才會執行__repr__()
  • 注:__repr__(obj)內置函數對應的結果是__repr__的返回值
  • 注:當使用%r格式化的時候會調用__repr__

__str__(self)的返回結果可讀性強。也就是說,__str__的意義是得到便于閱讀的信息,就像下面的 '2019-10-11' 一樣。

__repr__(self)的返回結果應更準確。也就是說,__repr__存在的目的在于調試,便于開發者使用。

例:

import datetimetoday = datetime.date.today() print(str(today)) # 2019-10-11 print(repr(today)) # datetime.date(2019, 10, 11) print('%s' %today) # 2019-10-11 print('%r' %today) # datetime.date(2019, 10, 11)

2.算術運算符

Python中可以在類中定義運算符對應的魔法方法,進而實現類對象的算術運算的操作。

  • __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()調用時的行為。
  • 注:未定義時power()與**操作結果相同
  • __lshift__(self,other)? ? ? ? ? ? ? ? ? ? ? ? ? 定義左移運算符 :<<
  • __rshift__(self,other)? ? ? ? ? ? ? ? ? ? ? ? ? 定義右移運算符 :>>
  • __and__(self,other)? ? ? ? ? ? ? ? ? ? ? ? ? ? 定義按位與 :&
  • __xor__(self,other)? ? ? ? ? ? ? ? ? ? ? ? ? ? ?定義按位異或 :^
  • __or__(self,other)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?定義按位或 :|

例:

class MyClass:def __init__(self, height, weight):self.height = heightself.weight = weight# 兩個對象的身高相加,體重相加。返回一個新的對象def __add__(self, others):return MyClass(self.height + others.height, self.weight + others.weight)# 兩個對象的身高相減,體重相減。返回一個新的對象def __sub__(self, others):return MyClass(self.height - others.height, self.weight - others.weight)# 說一下自己的參數def intro(self):print("高為", self.height, " 重為", self.weight)def main():a = MyClass(height=10, weight=5)a.intro()b = MyClass(height=20, weight=10)b.intro()c = b - ac.intro()d = a + bd.intro()if __name__ == '__main__':main()# 高為 10 重為 5 # 高為 20 重為 10 # 高為 10 重為 5 # 高為 30 重為 15

3.反算術運算符

反運算魔方方法,與算術運算符保持一一對應,不同之處就是反運算的魔法方法多了一個“r”。當文件左操作不支持相應的操作時被調用。

以定義加法的魔法方法為例,定義算術運算符+用__add__(self,other),反算術運算符+用__radd__(self,other)。上文所提所有運算符都有對應的反算術運算符。

反算術運算符的用處可以用a+b舉例,這里a是加數,b是被加數,當使用__add__(self,other)定義的+運算時,會將a傳給self,b傳給other,也就是調用對象a的__add__()方法。如果定義的__add__(self,other)不支持當前操作,或者__add__(self,other)沒有實現,Python就會調用對象b的__radd__(self,other)。換句話說就是如果a+b實現不了,就計算b+a。

例:

class Nint(int):def __radd__(self, other):return int.__sub__(other, self) # 注意 self 在后面a = Nint(5) b = Nint(3) print(a + b) # 8 print(1 + b) # -2 '''代碼解釋: 運算1 + b時,1是int類型的對象,b是Nint類型的對象 一開始先嘗試調用1.__add__(),由于不支持此類操作 系統便嘗試調用b.__radd__(),將b傳入self,1傳入other 返回的是int.__sub__(),1 + b的運算結果就變成1 - 3 '''

4.增量賦值運算符

Python中有增量賦值運算符,例如 += ,a += 2 與 a = a + 2等價。定義增量賦值運算符的魔法方法與算術運算符的魔法方法一一對應,不同之處在于名字前面多了一個“ i ”

  • __iadd__(self,other)? ? ? ? ? ? ? ? ? ? ? ?定義賦值加法:+=
  • __isub__(self,other)? ? ? ? ? ? ? ? ? ? ? ?定義賦值減法:-=
  • __imul__(self,other)? ? ? ? ? ? ? ? ? ? ? ?定義賦值乘法:*=
  • __itruediv__(self,other)? ? ? ? ? ? ? ? ??定義賦值真除法:/=
  • __ifloordiv__(self,other)? ? ? ? ? ? ? ? ?定義賦值整數除法://=
  • __imod__(self,other)? ? ? ? ? ? ? ? ? ? ? 定義賦值取模算法:%=
  • __ipow__(self,other[,module])? ? ? ?定義賦值冪運算:**=
  • __ilshift__(self,other)? ? ? ? ? ? ? ? ? ? ?定義賦值按位左移位:<<=
  • __irshift__(self,other)? ? ? ? ? ? ? ? ? ??定義賦值按位右移位:>>=
  • __iand__(self,other)? ? ? ? ? ? ? ? ? ? ??定義賦值按位與操作:&=
  • __ixor__(self,other)? ? ? ? ? ? ? ? ? ? ? ?定義賦值按位異或操作:^=
  • __ior__(self,other)? ? ? ? ? ? ? ? ? ? ? ? ?定義賦值按位或操作:|=

5.一元運算符

  • __neg__(self)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?定義正號:+x
  • __pos__(self)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?定義負號:-x
  • __abs__(self)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?定義被abs()調用時的行為,即絕對值
  • __invert__(self)? ? ? ? ? ? ? ? ? ? ? ? ? ? 定義按位取反:~x

6.屬性訪問

  • __getattr__(self,name)??? ? ? ? ? ? ? ?定義當用戶試圖獲取一個不存在的屬性時的行為。
  • __getattribute__(self,name)? ?定義當該類的屬性被訪問時的行為(先調用該方法,查看是否存在該屬性,若不存在,接著去調用__getattr__)。
  • __setattr__(self,name,value)? ? ? ? 定義當一個屬性被設置時的行為。
  • __delattr__(self,name)? ? ? ? ? ? ? ? ? 定義當一個屬性被刪除時的行為。

例:

class C:def __getattribute__(self, item):print('__getattribute__')return super().__getattribute__(item)def __getattr__(self, item):print('__getattr__')def __setattr__(self, key, value):print('__setattr__')super().__setattr__(key, value)def __delattr__(self, item):print('__delattr__')super().__delattr__(item)c = C() c.x # __getattribute__ # __getattr__c.x = 1 # __setattr__del c.x # __delattr__

7.描述符

描述符就是將某種特殊類型的類的實例指派給另一個類的屬性。

  • __get__(self,instance,owner)? ? ? ? 用于訪問屬性,它返回屬性的值。
  • __set__(self,instance,value)? ? ? ? ?將在屬性分配操作中調用,不返回任何內容。
  • __delete__(self,instance)? ? ? ? ? ? ?控制刪除操作,不返回任何內容。

例:

class MyDecriptor:def __get__(self, instance, owner):print('__get__', self, instance, owner)def __set__(self, instance, value):print('__set__', self, instance, value)def __delete__(self, instance):print('__delete__', self, instance)class Test:x = MyDecriptor()t = Test() t.x # __get__ <__main__.MyDecriptor object at 0x000000CEAAEB6B00> <__main__.Test object at 0x000000CEABDC0898> <class '__main__.Test'>t.x = 'x-man' # __set__ <__main__.MyDecriptor object at 0x00000023687C6B00> <__main__.Test object at 0x00000023696B0940> x-mandel t.x # __delete__ <__main__.MyDecriptor object at 0x000000EC9B160A90> <__main__.Test object at 0x000000EC9B160B38>

8.定制序列

Python有一種類叫協議(Protocols),協議與其它編程語言中的接口很相似,它規定你哪些方法必須要定義。然而,在 Python 中的協議就顯得不那么正式。事實上,在 Python 中,協議更像是一種指南。

容器類型相關的魔法方法有:

  • __len__(self)? ? ? ? ? ? ? ? ? ? ? ? ? ? 定義當被len()調用時的行為(返回容器中元素的個數)
  • __getitem__(self,key)? ? ? ? ? ? ? 定義 獲取容器中元素 的行為
  • __setitem__(self,key,value)? ? ?定義設置容器中指定元素的行為,相當于self[key] = value
  • __delitem__(self,key)? ? ? ? ? ? ? ?定義刪除容器中指定元素的行為,相當于del self[key]

而容器類型的協議有:

  • 如果希望定制的容器是不可變的,則只需要在類中定義__len__()和__getitem__()方法
  • 如果希望定制的容器是可變的,則除了要定義__len__()和__getitem__()方法外,還需要定義__setitem__()和__delitem__()方法

例:

class CountList: #定義可變類型的容器類def __init__(self, *args):self.values = [x for x in args]self.count = {}.fromkeys(range(len(self.values)), 0)def __len__(self):return len(self.values)def __getitem__(self, item):self.count[item] += 1 #統計容器內元素被訪問的次數return self.values[item]def __setitem__(self, key, value):self.values[key] = valuedef __delitem__(self, key):del self.values[key]for i in range(0, len(self.values)):if i >= key:self.count[i] = self.count[i + 1]self.count.pop(len(self.values))c1 = CountList(1, 3, 5, 7, 9) c2 = CountList(2, 4, 6, 8, 10) print(c1[1]) # 3 print(c2[2]) # 6 c2[2] = 12 print(c1[1] + c2[2]) # 15 print(c1.count) # {0: 0, 1: 2, 2: 0, 3: 0, 4: 0} print(c2.count) # {0: 0, 1: 0, 2: 2, 3: 0, 4: 0} del c1[1] print(c1.count) # {0: 0, 1: 0, 2: 0, 3: 0}

9.迭代器

  • 迭代是 Python 最強大的功能之一,是訪問集合元素的一種方式。
  • 迭代器是一個可以記住遍歷的位置的對象。
  • 迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。
  • 迭代器只能往前不會后退。
  • 字符串,列表或元組對象都可用于創建迭代器

迭代器有兩個基本方法:iter() 和 next()

  • iter(obj)? ? ? ? ? ? ? ? ? ? ? ? ?用于生成迭代器
  • next(iterator[,default])? ?返回迭代器的下一個項目。iterator指可迭代對象,即一個迭代器。default是可選參數,如果沒有下一個元素時返回默認值default,如果沒設置,又沒有下一個元素則會報錯

例:

links = {'B': '百度', 'A': '阿里', 'T': '騰訊'}it = iter(links) while True:try:each = next(it)except StopIteration:breakprint(each)# B # A # Tit = iter(links) print(next(it)) # B print(next(it)) # A print(next(it)) # T print(next(it)) # StopIteration

如果要定義一個類來當迭代器,則需要在類中實現兩個魔法方法__iter__()和__next__()

  • __iter__(self)? ? ? ? ?定義迭代容器中的元素的行為,返回一個特殊的迭代器對象, 這個迭代器對象實現了__next__()方法并通過StopIteration異常標識迭代的完成
  • __next__()? ? ? ? ? ? ?返回下一個迭代器對象
  • StopIteration?異常用于標識迭代的完成,防止出現無限循環的情況,在__next__()方法中我們可以設置在完成指定循環次數后觸發StopIteration異常來結束迭代

例:

class Fibs:def __init__(self, n=10):self.a = 0self.b = 1self.n = ndef __iter__(self):return selfdef __next__(self):self.a, self.b = self.b, self.a + self.bif self.a > self.n:raise StopIterationreturn self.afibs = 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 myGen():print('生成器執行!')yield 1yield 2myG = myGen() for each in myG:print(each)''' 生成器執行! 1 2 '''myG = myGen() print(next(myG)) # 生成器執行! # 1print(next(myG)) # 2 print(next(myG)) # StopIteration

三、學習問題與解答

本次學習所遇到的問題還是對大多數方法的不熟悉。尤其本次學習的主要就是方法,包括Python中最重要的魔法方法,在代碼運行時什么時候會調用魔法方法并不熟悉。主要還是需要多上手練習才能知道。

四、學習思考與總結

本次學習主要是學學習Python中的函數,或叫方法。從定義普通的函數,匿名函數和魔法函數都有很大的用處。魔法方法和類的運用可以做出很多簡潔又包括多方面功能的操作。主要是要多上手才能有更深的了解。

?

總結

以上是生活随笔為你收集整理的阿里云天池 Python训练营Task3: Python基础进阶:从函数到高级魔法方法 学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 99热这里 | 欧美亚洲黄色片 | 小蝌蚪av| 亚洲成av人片一区二区 | 初尝人妻少妇中文字幕 | 日韩网站在线 | 97超碰精品 | 日本不卡视频一区二区 | 欧美中文字幕第一页 | 伊人久久大香线蕉成人综合网 | 先锋av资源网站 | 超碰97人人草| 黄网站在线观看视频 | 成人特级片 | 51自拍视频 | 久久精品a | 国产东北真实交换多p免视频 | 姑娘第5集在线观看免费 | 一区二区三区视频在线播放 | 巨乳xxx| 日批免费网站 | 中文字幕在线成人 | 国产人妖一区二区三区 | 无毒黄色网址 | 精品免费观看 | 欧洲亚洲自拍 | 亚洲永久精品一区二区 | 亚洲av无码国产精品永久一区 | 国产又黄又粗又猛又爽的视频 | 片集网| 国产h片在线观看 | 少妇2做爰交换朴银狐 | www.黄在线观看 | 久久久片 | 无码人妻精品一区二区三区在线 | 小向美奈子在线观看 | 美女黄污网站 | 寡妇一级片 | 天天插日日干 | 欧美在线一区二区视频 | 成人三级在线播放 | 夜夜成人 | 一区二区三区视频免费视 | 在线蜜桃| 伊人黄色网 | 最新日韩视频 | 松本一香在线播放 | 男人久久天堂 | 99国产精品白浆在线观看免费 | 欧美亚洲一区 | 国产一区视频网站 | 成人免费观看a | 免费无遮挡无码永久视频 | 91九色在线视频 | 国产靠逼视频 | 一级福利片| 亚洲成人系列 | 亚洲欧美一区二区三区四区 | 亚洲精品一区二区三区不卡 | 婷婷色吧| 国产精品手机在线 | 在线观看你懂的网站 | 玖玖在线资源 | 欧美一级淫片 | 成年人深夜福利 | 日本福利小视频 | 国产精品久久影院 | 久久一二三区 | 一起草最新网址 | 久久99免费 | 日本精品成人 | 最新在线观看av | 成人国产精品久久久 | 欧美性一区 | 亚洲精品激情 | 国产精品国产精品国产专区蜜臀ah | 在线观看亚洲大片短视频 | 国内自拍青青草 | 精品一区二区久久久 | 午夜看片福利 | 波多野一区二区三区 | 抖音视频在线观看 | 日本欧美久久久久免费播放网 | 天天摸天天碰 | 九一毛片 | 好吊操这里有精品 | 国产精品福利电影 | 亚洲男人天堂网站 | 免费无码不卡视频在线观看 | 一本免费视频 | 青青草原一区二区 | 久草视频免费在线播放 | 亚洲福利视频一区 | 最近中文字幕在线mv视频在线 | 国产激情亚洲 | 四虎精品久久 | 欧美成人aaa片一区国产精品 | 欧美影院一区二区 | 三级网站在线看 |