python 函數練習題


函數的結構和參數

定義一個函數
def len_num(a):
    return len(a)
b=len_num([123,1,2])#函數名加括號就調用了 
print(b)

# 結構:
#def 關鍵字,定義函數。
#len_num 函數名:與變量設置相同,具有可描述性。
#函數體 :縮進。函數中盡量不要出現print
# return后面是返回值(len(a)) 在函數中遇到return直接結束函數。
    # return 將數據返回給函數的執行者,調用者 len_num()。
    # return 返回單個元素 是返回原有數據類型的形式返回
    # return 返回多個元素 是以元組的形式返回給函數的執行者。
    
形參的最終順序為:
	**位置參數,
	*args,
	默認參數,
	僅限關鍵字參數,
	**kwargs

實參角度:
    1. 位置參數 按照順序,一一對應
    2. 關鍵字參數, 一一對應
    3. 混合參數:位置參數一定要在關鍵字參數的前面。
    
1.萬能參數: *args, 約定俗稱:args,
    函數定義時,*代表聚合。 他將所有的位置參數聚合成一個元組,賦值給了 args。
2.**kwargs 僅限關鍵字參數
    1.函數的定義時: ** 將所有的關鍵字參數聚合到一個字典中,將這個字典賦值給了kwargs.
    
1.*在函數的調用時,*代表打散。
    **{'name': '太白'}打散為name='太白' 
    *[1,2,3]打散為1,2,3
2.函數外:處理剩余元素
    a,b,*c = [1,2,3,4,5]

函數的取值順序 加載順序 作用域

# 內置名稱空間:python源碼給你提供的一些內置的函數,print input
python分為三個空間:
    1.內置名稱空間(builtins.py)
    2.全局名稱空間(當前py文件)
    3.局部名稱空間(函數,函數執行時才開辟)

加載順序:
內置名稱空間 ---> 全局名稱空間  ----> 局部名稱空間(函數執行時)

取值順序(就近原則) 單向不可逆
從局部找時 局部名稱空間  ---> 全局名稱空間  --->  內置名稱名稱空間

兩個作用域:
    1.全局作用域 :內置名稱空間 全局名稱空間
    2.局部作用域:局部名稱空間(函數等)
注意
1.局部作用域可以引用全局作用域的變量
2.局部作用域不能改變全局變量。 可以使用,不能改變
3.注意 python中不可以先引用 后定義

函數名的應用

1.函數名是一個特殊的變量。
2.函數名指向的是函數的內存地址,加上()就執行這個函數。
3. 函數名可以作為容器類類型的元素。
4. 函數名可以作為函數的實參。
5. 函數名可以作為函數的返回值。

構造函數和析構函數

構造函數,用於創建對象的函數。
析構函數,用於銷毀對象的函數。

class Foo(object):
	def __new__(self,*args,**kwargs): # 構造函數
		pass 
	
	def __del__(self,*args,**kwargs): # 析構函數
		pass 
obj = Foo()
del obj

重寫和重載的區別?

class Foo(object):

	def f1(self,int a1):
		return 123
		
	def f1(self,string a1):
		pass
		
重載,函數名相同而參數類型/個數/返回值不同。
class Foo(object):
	def f1(self):
		print(123)
		
class Bar(Foo):
	def f1(self):
		print(666)
		
重寫,在子類中對父類中的方法進行重寫。

什么是接口?

定義一個接口對繼承類進行約束,接口里有什么方法,繼承類就必須有什么方法,接口中不能任何功能代碼


強制約束
抽象類,可以說是類和接口的混合體,既可以定義常規方法,也可以約束子類的方法(抽象方法)

lambda表達式格式以及應用場景?

匿名函數:為了解決那些功能很簡單的需求而設計的一句話函數 與內置函數結合
函數名 = lambda 參數 :返回值

1.參數可以有多個,用逗號隔開
2.匿名函數不管邏輯多復雜,只能寫一行,且邏輯執行結束后的內容就是返回值
3.返回值和正常的函數一樣可以是任意數據類型

lambda 表達式
temp = lambda x,y:x+y
print(temp(4,10))   # 14

可替代:
def foo(x,y):
    return x+y
print(foo(4,10))    # 14

和內置函數結合
1.min max()可以加功能
2.reversed() 將一個序列翻轉
3.sorted排序函數 可以加key
4.map對元素進行映射
5.filter篩選過濾 返回迭代器

*arg和**kwarg作用

*args代表位置參數,它會接收任意多個參數並把這些參數作為元祖傳遞給函數。
**kwargs代表的關鍵字參數,返回的是字典,位置參數一定要放在關鍵字前面

Python垃圾回收機制?

1.引用計數
引用計數法有很明顯的優點:
    對象有確定的生命周期
    易於實現
    原始的引用計數法也有明顯的缺點:
    維護引用計數消耗資源,維護引用計數的次數和引用賦值成正比,而不像mark and sweep等基本與回收的內存數量有關。
    無法解決循環引用的問題。A和B相互引用而再沒有外部引用A與B中的任何一個,它們的引用計數都為1,但顯然應該被回收。
    為了解決這兩個致命弱點,Python又引入了以下兩種GC機制。

2.標記清除
	標記-清除”法是為了解決循環引用問題。可以包含其他對象引用的容器對象

3.分代回收
	Python默認定義了三代對象集合,索引數越大,對象存活時間越長

列舉常見的內置函數

1.abs()  print(abs(a))  #輸出3
返回數字的絕對值

2.all()     此函數用於判斷給定的可迭代參數 iterable 中的所有元素是否都不為 0、都不為False 或者iterable都 為空,如果是返回 True,否則返回 False。
3.any()     函數用於判斷給定的可迭代參數 iterable 是否全部為空對象,如果都為空、都為0、或者都為false,則返回 False,如果不都為空、不都為0、不都為false,則返回 True。

3.print()
print函數是你學Python接觸到的第一個函數,它將對象輸出到標准輸出流,可將任意多個對象打印出來

4.isinstance()
可以用 isinstance 函數判斷某個對象是否屬於某個類的實例,函數的定義

range()
range函數是個工廠方法,用於構造一個從[start, stop) (不包含stop)之間的連續的不可變的整數序列對象,這個序列功能上和列表非常類似,函數定義:

enumerate()
用於枚舉可迭代對象,同時還可以得到每次元素的下表索引值,函數定義:

len()

zip()
                      
                      
sep 設定分隔符。
print(1, 2, 3, sep='|')
end去除默認換行
print(1, 2, end=' ')
abs() 獲取絕對值
print(abs(-10))
sum() 數字相加求和
# sum() 數字相加求和 會for循環里面元素 必須里面都是由int組成 注意列表 sum(iterable,)
print(sum([1, 2, 3, 4], 100))
min max()可以加功能
# min 可以加功能 key 與匿名函數結合
# min 可以加功能
# print(min([22, 11, 45, 2]))
# l1 = [(73, 'alex'), (35, '武大'), (18, '太白')]
# print(min(l1,key=lambda x: x[0]))
# print(min(l1,key=lambda x: x[0])[0])
# 第一步 循環遍歷l1 將里面的元素以形參的方式傳給匿名函數得到返回值
# 第2步  利用內置函數比較返回值 得到想要的結果,在將傳進去的元素返回
reversed() 將一個序列翻轉
# reversed() 將一個序列翻轉, 返回翻轉序列的迭代器 reversed 示例:
# l = reversed('123')  # l 獲取到的是一個生成器 注意字符串轉list會分隔
# print(list(l))
sorted排序函數 可以加key
# lst = [{'id': 1, 'name': 'alex', 'age': 18},
#        {'id': 2, 'name': 'wusir', 'age': 17},
#        {'id': 3, 'name': 'taibai', 'age': 16}, ]
# # 按照年齡對學生信息進行排序
# print(sorted(lst, key=lambda e: e['age']))
l = ['班級24','班級15','班級3','班級5','班級25']#,按照數字的順序從大到小排序,不改變原列表,請以最少代碼量實現。(3分)
print(sorted(l, key=lambda e: int(e[2:]),reverse=False))
map對元素進行映射
# map(function,iterable) 可以對可迭代對象中的每一個元素進行映射,分別取執行function
# 計算列表中每個元素的平方,返回新列表
# lst = [1,2,3,4,5]
# def func(s):
#     return  s*s
# mp = map(func,lst)
# print(mp)#對象
# print(list(mp))
# # 改寫成lambda
# print(list(map(lambda s:s*s,lst)))
zip() 拉鏈方法
# zip() 拉鏈方法。函數用於將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,
# 然后返回由這些元祖組成的內容,如果各個迭代器的元素個數不一致,則按照長度最短的返回
# lst1 = [1,2,3]
# lst2 = ['a','b','c','d']
# lst3 = (11,12,13,14,15)
# for i in zip(lst1,lst2,lst3):
#     print(i)
filter篩選過濾 返回迭代器
filter篩選過濾 返回迭代器
ls = filter(lambda e:e['age'] > 16,lst)

列表推導式與生成器推導式

print([ i % 2 for i in range(10) ])  # [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
print([ i  for i in range(10) ])     # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print([ 10 % 2])   # [0]
# %是個運算符。

print(( i % 2 for i in range(10) ))
#  <generator object <genexpr> at 0x00000000020CEEB8> 生成器
# 在Python中,有一種自定義迭代器的方式,稱為生成器(Generator)。
# 定義生成器的兩種方式:
# 1.創建一個generator,只要把一個列表生成式的[]改成(),就創建了一個generator:
# generator保存的是算法,每次調用next(),就計算出下一個元素的值,直到計算到最后一個元素,
沒有更多的元素時,拋出StopIteration的錯誤。
# 2.定義generator的另一種方法。如果一個函數定義中包含yield關鍵字,那么這個函數就不再是一個普通函數,
而是一個generator

def func(a,b=[]) 這種寫法有什什么坑?

def func(a,b = []):
    b.append(1)
    print(a,b)

func(a=2)
func(2)
func(2)


'''
    2 [1]
    2 [1, 1]
    2 [1, 1, 1]
    函數的默認參數是一個list 當第一次執行的時候實例化了一個list 
    第二次執行還是用第一次執行的時候實例化的地址存儲 
    所以三次執行的結果就是 [1, 1, 1] 想每次執行只輸出[1] ,默認參數應該設置為None

如何在函數中設置一個全局變量

x = 2
def func():
    global x
    x = 1
    return x
func()
print(x)  # 1

簡述 生成器、迭代器、可迭代對象 以及應用場景?

可迭代對象
    1.可以進行循環更新的一個實實在在值。
    2.如何判斷一個對象是否是可迭代對象: 利用內置函數:dir()可以查看對象內部方法
    3.有__iter__方法的對象,都是可迭代對象。
    4.str,list set tup 逗是可迭代對象
        print('__iter__' in dir(str))#True
    ps dir()函數可以獲取對象所有方法

迭代器
    1.可更新迭代的工具
    2.在python中,內部含有'__iter__'方法並且含有'__next__'方法的對象就是迭代器。
    3.迭代器可以迭代取值。利用next()進行取值(節省內存)或者轉為list 元祖等等取值
    4.一個next()取一個值 且會記錄位置 迭代器一條路走到底,不走回頭路。
    5.取完了再next()會報錯(StopIteration) 我們可以用try處理 萬能異常(Exception)
    
可迭代對象轉化成迭代器
    利用內置函數iter()
    l1=[1,2,3]
    obj = iter(l1)
    object.__iter__()

1.可迭代對象是一個操作方法比較多,比較直觀,存儲數據相對少(幾百萬個對象,8G內存是可以承受的)的一個數據集。
2.當你側重於對於數據可以靈活處理,並且內存空間足夠,將數據集設置為可迭代對象是明確的選擇。
3.是一個非常節省內存,可以記錄取值位置,可以直接通過循環+next方法取值,但是不直觀,操作方法比較單一的數據集。
4.當你的數據量過大,大到足以撐爆你的內存或者你以節省內存為首選因素時,將數據集設置為迭代器是一個不錯的選擇。

生成器
1.將return換為yield就是生成器函數
2.只要函數中出現了yield那么他就不是函數,它是生成器函數。
3.不結束函數,對應着給 next 返回值(多個值通過元組的形式返回)。 會記錄位置
4.生成器是一個返回迭代器的函數,只能用於迭代操作,更簡單點理解生成器就是一個迭代器。

裝飾器

裝飾器:
能夠在不修改原函數代碼的基礎上,在執行前后進行定制操作,閉包函數的一種應用 不修改被修飾函數的代碼


場景:
   - flask路由系統
   - flask before_request
   - csrf
   - django內置認證
   - django緩存
# 手寫裝飾器;
import functools
def wrapper(func):
   @functools.wraps(func)  #不改變原函數屬性
   def inner(*args, **kwargs):
      #執行函數前
      return func(*args, **kwargs)
      #執行函數后
   return inner
1. 執行wapper函數,並將被裝飾的函數當做參數。 wapper(index)
2. 將第一步的返回值,重新賦值給  新index =  wapper(老index)
@wrapper    #index=wrapper(index)
def index(x):
   return x+100

用Python實現一個二分查找的函數。

二分查找算法:簡單的說,就是將一個列表先排序好,比如按照從小到大的順序排列好,當給定一個數據,比如3,查找3在列表中的位置時,可以先找到列表中間的數li[middle]和3進行比較,當它比3小時,那么3一定是在列表的右邊,反之,則3在列表的左邊,比如它比3小,則下次就可以只比較[middle+1, end]的數,繼續使用二分法,將它一分為二,直到找到3這個數返回或者列表全部遍歷完成(3不在列表中) 

優點:效率高,時間復雜度為O(logN); 
缺點:數據要是有序的,順序存儲。

li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
def search(someone, li):
    l = -1
    h = len(li)
 
    while l + 1 != h:
        m = int((l + h) / 2)
        if li[m] < someone:
            l = m
        else:
            h = m
    p = h
    if p >= len(li) or li[p] != someone:
        print("元素不存在")
    else:
        str = "元素索引為%d" % p
        print(str)
 
search(3, li)  # 元素索引為2

談談你對閉包的理解?

ef foo():
    m=3
    n=5
    def bar():
        a=4
        return m+n+a
    return bar
  
>>>bar =  foo()
>>>bar()

種內部函數可以使用外部函數變量的行為,就叫閉包。或者有自由變量

是否使用過functools中的函數?其作用是什么?

用於修復裝飾器  flask源碼里面有用到

import functools
 
def deco(func):
    @functools.wraps(func)  # 加在最內層函數正上方
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
 
    return wrapper
 
 
@deco
def index():
    '''哈哈哈哈'''
    x = 10
    print('from index')
 
 
print(index.__name__)
print(index.__doc__)
 
# 加@functools.wraps
# index
# 哈哈哈哈
 
# 不加@functools.wraps
# wrapper
# None

異常處理寫法以及如何主動跑出異常(應用場景)

# 觸發異常
def temp_convert(var):
    try:
        return int(var)
    except ValueError as Argument:
        print ("參數沒有包含數字%s"%Argument)

# 調用函數
temp_convert("xyz")
# 以10為基數的int()的無效文字:“xyz”

----------------------------------------------------------------------------
# raise語法
#raise [Exception [, args [, traceback]]]
# 語句中 Exception 是異常的類型,args 是自已提供的異常參數。

class Networkerror(RuntimeError):
    def __init__(self, arg):
        self.args = arg
try:
    raise Networkerror("Bad hostname")
except Networkerror as e:
    print(e.args)

yield和yield from關鍵字

yield 返回一個
yield from 返回一堆

1.yield from 將一個可迭代對象的每一個元素返回給next
2.yield from 節省代碼,提升效率(代替了for循環)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM