Python函数和面向对象,小白看了都说好
Python函數和面向對象,小白看了都說好
python除了使用內置函數以外,還可以自定義函數。我們為什么要定義和使用函數呢?
下面我舉個例子,比如我想求10的階乘
# 求10的階乘 m = 1 for i in range(1, 11):m *= i print(m)代碼雖然不長,但是如果我還想求20,21,55,100的階乘呢?按照上面的方式求幾個數的階乘就要寫幾個循環,這樣我們也能得到想要的答案,但代碼是不是顯得’難看‘。這時候我們就可以定義一個函數,以后求階乘只需要調用這個函數就行了。
# 求n的階乘 def fac(n):result = 1for i in range(1, n + 1):result *= ireturn resultfac(8) # 8的階乘 fac(25) # 25的階乘 fac(63) # 63的階乘 fac(100) # 100的階乘是不是感覺很方便呢?接下來給大家介紹一下函數用法
定義函數
定義一個python函數,下面是函數的基本形式:
def 函數名(參數1,參數2,…,參數n):
? 函數體
? return 返回值
我們可以看到python用def來定義一個函數,后面有函數名和英文括號(括號里面可以定義一些參數,參數可以根據具體需求設置,也可以沒有參數,參數還可以設置默認值)。下面return可以返回一個值,這個值有時任何形式的數據,當然也可以沒有返回值。
接下來是一些實例:
實例1:
def hello_world():return 'hello, world'print(hello_world()) # hello, world實例2:
def hello(name):print(f'你好,{name}')hello('百里守約') # 你好,百里守約實例3:
# 多個數累加 def add(nums):sum = 0for n in nums:sum += nreturn sumnums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] print(add(nums)) # 55函數的返回值
return:返回值,如果沒有則默認返回None
實例:
實例:
s = 'hello, 張三'return sdef hello2():print('hello, jack')a = hello() print(a) #hello, 張三 b = hello2() #hello, jack函數參數
函數可以設置參數,也可以不設置參數,可以設置一個參數,也可以設置多個參數,同時函數也可以設置默認值。
實例:
import random# 搖色子 def roll_dice(n=2):"""搖色子:param n: 色子個數,默認兩個色子:return: 返回色子的總點數"""# points 表示總點數points = 0for _ in range(n):points += random.randrange(1, 7)return pointsprint(roll_dice()) # 默認值為2,搖兩個色子,沒有默認值調用函數時必須傳入參數值 print(roll_dice(3)) # 傳入參數3,此時n=3,表示搖3個色子實例:
def BMI(high, weight, sex):"""體質指數計算:param high:身高 ,單位:米:param weight:體重,單位:千克、公斤:param sex:性別,男:1,女:0:return: 返回體質指數"""bmi = weight / high ** 2if sex == 0:bmi -= 1.1if bmi < 19:print('體重偏輕')elif 19 <= bmi < 25:print('健康體重')elif 25 <= bmi < 30:print('超重')elif 30 <= bmi < 39:print('嚴重超重')else:print('極度超重')return weight / high ** 2print(BMI(1.6, 50, 1))此時我們在設置了三個參數,當調用函數時,我們也必須傳入三個參數,輸入參數 的位置默認和設置參數的位置一致。如果參數有默認值,則調用函數時,帶有默認值的參數可以不必輸入。
實例
# 加法函數 def sum(a, b):"""加法函數,將a和b相加:param a: 加數:param b: 加數:return: 返回相加之和"""return a+bprint(sum(1, 2))實例:
# 加法函數 def sum(a, b, c, d, e):"""加法函數,將a, b, c, d, e相加:return: 返回相加之和"""return a+b+c+d+eprint(sum(1, 2, 3, 4, 5))當輸入的參數過多,并且參數的屬性一致時,我們可以使用可變參數
可變參數
# 加法函數 def sum(*a):"""加法函數:param a: 表示一個可變參數,存儲任意多參數,此時a為一個元組:return: 返回相加之和"""m = 0for i in a:m += ireturn mprint(sum(1, 2, 3)) print(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))在參數前面加*號,此時參數為可變參數。可變參數為一個元組,將所有多余的參數全部存在里面。
同時我們可以在不同的項目中調用函數
實例:
module1.py
def hello():print('hello, world')module2.py
def hello():print('goodbye, world')test.py
import module1 import module2# 用“模塊名.函數名”的方式(完全限定名)調用函數, module1.hello() # hello, world module2.hello() # goodbye, world在導入模塊時,還可以使用as關鍵字對模塊進行別名,這樣我們可以使用更為簡短的完全限定名。
import module1 as m1 import module2 as m2m1.hello() # hello, world m2.hello() # goodbye, world如果我們用from…import…的形式,我們必須使用as關鍵字對導入函數進行別名,不然兩個相同的hello函數,其中一個會被覆蓋。
from module1 import hello as h1 from module2 import hello as h2h1() # hello, world h2() # goodbye, world標準庫中的模塊和函數
| abs | 返回一個數的絕對值,例如:abs(-1.3)會返回1.3。 |
| bin | 把一個整數轉換成以'0b'開頭的二進制字符串,例如:bin(123)會返回'0b1111011'。 |
| chr | 將Unicode編碼轉換成對應的字符,例如:chr(8364)會返回'€'。 |
| hex | 將一個整數轉換成以'0x'開頭的十六進制字符串,例如:hex(123)會返回'0x7b'。 |
| input | 從輸入中讀取一行,返回讀到的字符串。 |
| len | 獲取字符串、列表等的長度。 |
| max | 返回多個參數或一個可迭代對象(后面會講)中的最大值,例如:max(12, 95, 37)會返回95。 |
| min | 返回多個參數或一個可迭代對象(后面會講)中的最小值,例如:min(12, 95, 37)會返回12。 |
| oct | 把一個整數轉換成以'0o'開頭的八進制字符串,例如:oct(123)會返回'0o173'。 |
| open | 打開一個文件并返回文件對象(后面會講)。 |
| ord | 將字符轉換成對應的Unicode編碼,例如:ord('€')會返回8364。 |
| pow | 求冪運算,例如:pow(2, 3)會返回8;pow(2, 0.5)會返回1.4142135623730951。 |
| 打印輸出。 | |
| range | 構造一個范圍序列,例如:range(100)會產生0到99的整數序列。 |
| round | 按照指定的精度對數值進行四舍五入,例如:round(1.23456, 4)會返回1.2346。 |
| sum | 對一個序列中的項從左到右進行求和運算,例如:sum(range(1, 101))會返回5050。 |
| type | 返回對象的類型,例如:type(10)會返回int;而type('hello')會返回str。 |
函數進階
位置參數和關鍵字參數
def add(a,b,c):當我想調用函數add時,如add(1,2,3),此時a = 1,b = 2,c = 3,也就是說,傳入的參數值與原來函數的參數位置一一對應。此時參數都是位置參數,當然,我們也可以通過參數名=參數值的方式進行傳參,如add(a=1,c=3,b=2),因為傳入參數時帶上了參數名,所以參數位置可以隨意改變。
如果我們希望調用函數時必須以參數名=參數值的格式進行傳參,我們對函數參數做如下改變:
def add(*,a,b,c):如此,如果想調用add函數,必須要以參數名=參數值的格式進行傳參,否則就會引發異常,這時候的參數我們稱之為關鍵字參數。
| def add(a, b, c) | a、b、c 都是位置參數 | add(1, 2, 3) |
| def add(*, a, b, c) | a、b、c 都是關鍵字參數 | add( a = 1, b = 2, c = 3) |
| def add(a, *, b, c) | a 是位置參數,b、c 是關鍵字參數 | add( 1, b = 2, c = 3) |
簡單來說,* 前面的參數都是位置參數, * 后面的參數都是關鍵字參數
前面我們說到可變參數 ( *參數名 )可以容納任意多的參數個數,我們在設計函數時,如果既不知道調用者會傳入的參數個數,也不知道調用者會不會指定參數名,那么同時使用可變參數和關鍵字參數。關鍵字參數會將傳入的帶參數名的參數組裝成一個字典,參數名就是字典中鍵值對的鍵,而參數值就是字典中鍵值對的值
def calc(*args, **kwargs):*args 為可變參數,返回的是一個元組
**kwargs 為可變的關鍵字參數,返回的是一個字典
實例:
# 加法函數 def sum(*args, **kwargs):result = 0for arg in args: # args 為元組result += argfor value in kwargs.values(): # kwargs為字典result += valuereturn resultprint(sum(1, 3, 5)) # 9 print(sum(a = 1, b = 4, c = 3)) # 8 print(sum(1, 5, c = 7, d = 3)) # 16設計函數時,位置參數必須在關鍵字參數前面;沒有默認值的參數必須在有默認值的參數前面。
高級函數
函數本身也可以作為函數的參數或者返回值,這樣的函數我們稱之為高級函數。
# 加法 def add(num1, num2):return num1 + num2# 減法 def sub(num1, num2):return num1 - num2# 乘法 def mul(num1, num2):return num1 * num2# 除法 def div(num1, num2):return num1 / num2# 高級函數 def sum(*args, start, ft, **kwargs):"""高級函數,自由實現多個數的四則運算start:開始值,加法運算時為0,減法、乘法、除法運算時為0ft:函數名"""result = start_valuefor arg in args: #result = ft(result, arg)for value in kwargs.values():result = ft(result, value)return resultprint(sum(1, 3, 5, start = 0, ft = add, a = 1, b = 4, c = 3)) # 加法 17 print(sum(1, 3, 5, start = 1, ft = sub, a = 1, b = 4, c = 3)) # 減法 -16 print(sum(1, 3, 5, start = 1, ft = mul, a = 1, b = 4, c = 3)) # 乘法 180 print(sum(1, 3, 5, start = 1, ft = div, a = 1, b = 4, c = 3)) # 除法 0.005555555555555556此時函數sum已經不局限于一個加法函數,而是可以輕松可以進行四則運算里面任何一個計算方式。需要注意的是,將函數作為參數和調用函數是有顯著的區別的,調用函數需要在函數名后面跟上圓括號,而把函數作為參數時只需要函數名即可。我們還可以直接調python標準庫中operator模塊,它可以提供加法乘法運算,我們直接使用即可。
Lambda函數(匿名函數)
Lambda函數又叫你們函數是一種沒有函數名的函數
表達式 ------- lambda 參數1 , …, 參數n : 執行體
執行體通常是一個表達式,其返回值通常就是運算結果
實例:
def sum(*args, start=0, ft=lambda x, y: x + y, **kwargs):result = startfor arg in args:result = ft(result, arg)for value in kwargs.values():result = ft(result, value)return result# 使用默認的lambda函數 print(sum(1, 3, 5, x = 7, y = 9)) # 25 # 重新定義lanbda函數 print(sum(1, 3, 5, x = 7, y = 9, start = 1, ft = lambda x, y: x * y)) # 945面向對象
首先給大家介紹幾個重要的概念。
- 類、對象
類是一個抽象的概念,對象是類的具體實現。
把屬于同一個類的共同特征提取出來,我們就得到一個類,比如人是一個類,小明、張三、李四就是一個具體的對象;天體是一個類,那么地球、火星、月球就是一個具體的對象。
-
封裝、繼承、多態
封裝:把數據和操作數據的函數從邏輯上組裝成一個整體(對象)。隱藏實現細節,暴露簡單的調用接口。
繼承:擴展已有的類創建新類,實現對已有類的代碼復用。
多態:給不同的對象發出同樣的消息,不同的對象執行了不同的行為。
簡單概括一下面向對象編程就是:把一組數據和處理數據的方法組成對象,把行為相同的對象歸納為類,通過封裝隱藏對象的內部細節,通過繼承實現類的特化和泛化,通過多態實現基于對象類型的動態分派。是一種重要的編程思維和方式。
定義類
加上類名來定義類,通過縮進我們可以確定類的代碼塊,就如同定義函數那樣。在類的代碼塊中,我們需要寫一些函數,我們說過類是一個抽象概念,那么這些函數就是我們對一類對象共同的動態特征的提取。寫在類里面的函數我們通常稱之為方法,方法就是對象的行為,也就是對象可以接收的消息。方法的第一個參數通常都是self,它代表了接收這個消息的對象本身。
創建和使用對象
# 定義一個學生類,里面包含學習和玩兩個方法 class Student:def study(self, course):print(f'學習{course}。')def play(self, name, game):print(f'玩{game}')if __name__ == '__main__':student1 = Student() # 創建一個對象,命名student1student2 = Student() # 創建一個對象,命名student2# 調用學生類中的方法student1.study('語文') # 學習語文。student2.study('數學') # 學習數學。student1.play('連連看') # 玩連連看student1.play('推箱子') # 玩推箱子初始化方法
我們可以通過給Student類添加__init__方法的方式為學生對象指定屬性,同時完成對屬性賦初始值的操作,這個方法方法通常也被稱為初始化方法。我們對上面的Student類修改,給學生對象添加name(姓名)和age(年齡)兩個屬性。
# 定義一個學生類,里面包含學習和玩兩個方法 class Student:def __init__(self, name, age):self.name = nameself.age = agedef study(self, course):print(f'{self.name}學習{course}。')def play(self, game):print(f'{self.name}玩{game}')if __name__ == '__main__':student1 = Student('張三', 15) # 創建一個對象,命名student1student2 = Student('李四', 16) # 創建一個對象,命名student2# 調用學生類中的方法student1.study('語文') # 張三學習語文。student2.study('數學') # 李四學習數學。student1.play('連連看') # 張三玩連連看student1.play('推箱子') # 張三玩推箱子在Python中,以兩個下劃線開頭和結尾的方法,我們一般稱之為魔術方法或魔法方法。通過__repr__魔術方法,如果我們在打印對象的時候看到的是我們自定義的信息,該方法返回的字符串就是用print函數打印對象的時候會顯示的內容。
# 定義一個學生類,里面包含學習和玩兩個方法 class Student:def __init__(self, name, age):self.name = nameself.age = agedef study(self, course):print(f'{self.name}學習{course}。')def play(self, game):print(f'{self.name}玩{game}')def __repr__(self):return f'{self.name}: {self.age}'if __name__ == '__main__':student1 = Student('張三', 15) # 創建一個對象,命名student1print(student1) # 張三: 15students = [student1, Student('老李四', 16), Student('王五', 25)]print(students) # [張三: 15, 老李四: 16, 王五: 25]小程序:
class Clock:"""時間"""def __init__(self, hour=0, minute=0, second=0):self.second = secondself.minute = minuteself.hour = hourdef run(self):self.second += 1if self.second == 60:self.second = 0self.minute += 1if self.minute == 60:self.minute = 0self.hour += 1if self.hour == 24:self.hour = 0def show(self):return f'{self.hour:0>2d}:{self.minute:0>2d}:{self.second:0>2d}'if __name__ == '__main__':clock = Clock(23, 59, 50)while True:os.system('cls')print(clock.show())time.sleep(1)clock.run()后續還會繼續更新,感興趣的伙伴可以留意
繼承和多態
面向對象的編程語言支持在已有類的基礎上創建新類,從而減少重復代碼的編寫,我們稱之為繼承。提供繼承信息的類叫做父類(超類、基類),得到繼承信息的類叫做子類(派生類、衍生類),子類可以獲得類所有的方法(私有方法除外),同時子類還可定義自己的方法,子類繼承父類的方法后,還可以對方法進行重寫(重新實現該方法),不同的子類可以對父類的同一個方法給出不同的實現,這樣的方法在程序運行時就會表現出多態行為(調用相同的方法,做了不同的事情),我們稱之為多態。實例如下:
歡迎大家在下方留言評論,一起交流學習~
總結
以上是生活随笔為你收集整理的Python函数和面向对象,小白看了都说好的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 「镁客·请讲」移康智能朱鹏程:做产品就要
- 下一篇: JVM(2)垃圾收集器