Python(函數與面向對象)

Python(函數與面向對象)

@(Knowledge)[Python, Auspice Vinson]


函數(function)

函數也是 對象
保存可執行代碼,並可重複調用

定義函數

函數名中保存內存首地址

def 函數名([形參1,形參2...]):
	代碼塊

調用函數

函數名()

參數(形參)

形參聲明變量,但不賦值

  • 形參可指定默認值
  • 調用時不傳參,默認值生效
def fn(a,b,c = 20):
	print(c)

fn(1,2,3)# 3

實參

調用函數時,傳遞的參數

  • 關鍵字參數和位置參數可混合使用
  • 混合使用時,位置參數必須在關鍵字參數前面
  • 同一形參只能賦值一次
位置參數

將對應位置實參,賦值給對應的形參

關鍵字參數

直接根據參數名傳遞參數

fn(b = 1,c = 3,a = 2)
實參類型

解析器不會檢查實參類型
包括函數

  • 如果形參指向的是一個對象,修改會影響指向對象的值
c = [1,2,3]

fn(c.copy())
fn(c[:])

不定長參數

形參前加 * ,將獲取所有剩餘形參保存至元組

  • 接收所有位置實參,將這些實參保存到同一個元組
  • 裝包參數最好放於參數列表末尾
    • 若裝包參數位於參數列表中間,其後參數必須以關鍵字參數形式傳遞
    • 關鍵字參數必須放於參數列表最後
def fn(a,*b,c):
	print(a,b,c)
	# a=1,b=(2,3,4),c=5
f(1,2,3,4,c=5)
  • 帶 * 形參只能寫一個
# 求任意數字的和
def sum(*a):
	print("a=",a,type(a))# tuple
	result = 0
	for i in a:
		result += n
	return n
  • 要求所有參數以關鍵字形式傳遞
def fn(*,a,b,c):
	pass
  • *參數只能接收位置參數
  • ** 可以接受其他關鍵字參數,保存至字典
    • 鍵:關鍵字參數名
    • 值:參數值
    • 只能有一個
    • 只能寫在參數列表最後
def fn(**a):
	pass
	# a = {'a':1,'b':2,'c':3}
fn(a=1,b=2,c=3)

參數解包

def fn(a,b,c):
	pass

t = (10,11,12)
fn(*t)
  • 序列中元素個數與形參個數一致
  • *序列解包
  • **字典解包
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LxGWf5pr-1587303200314)(./1585301982654.png)]
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-8ZFdDvPH-1587303200318)(./1585301991659.png)]

返回值

關鍵字 return

  • 如果return後不寫或沒有return ,返回空
  • return用來結束函數

文檔字符串

直接在函數第一行寫一個字符串

def fn(a:int,b:bool,b:str = 'Hello')-> int:
	```
	文檔字符串實例
	形參列表,參數名後加:表明參數類型
	函數聲明 -> 表示返回類型
	```
	return 10

help(fnName)

查詢python中函數用法

作用域(scope)

變量生效區域

  1. 兩種作用域
  • 全局作用域:
    • 在程序執行時創建,程序結束時銷燬
    • 所有函數以外的區域
  • 函數作用域
    • 在函數調用時創建 ,調用結束銷燬
    • 每調用一次,產生新的函數作用域
    • 函數作用域中定義的變量,是局部變量,只能在函數內部訪問
  1. 作用域嵌套
  • 賦值默認爲當前作用域
  1. 同名變量
  • 優先在當前作用域尋找,如果有則使用
  • 當前作用域沒有,去上一級作用域查找
  1. 函數內部修改全局變量
  • global聲明變量
  • global a

命名空間(namespace)

變量作用域

  • 每個變量都需要存儲到指定的命名空間內
  • 存儲變量的字典
  1. 全局命名空間
  • 保存全局變量
  1. 函數命名空間
  • 保存函數中的變量

locals()

獲取當前作用域的命名空間

  1. 向scope添加變量
  • 向字典中添加鍵值對
scope = locals()
scope['c'] = 1000
  1. 只用於查看當前命名空間
  2. 外部不能訪問內部

global()

在任意命名空間中獲取全局命名空間

遞歸

將大問題分解爲小問題,知道不可再分
解決小問題

  • 遞歸與循環基本可互相轉換
  • 可用循環優化代碼
# 遞歸求階乘
def fac(n):
	if n==1:
		return 1
	else:
		return n*fab(n-1)
# 漢諾塔實踐
# 函數定義
# def hanoi (n, src, dst, mid):
#     pass
# 參數說明
# n是整數,表示圓柱 A 上面的圓盤個數。
# src是大寫字母A,表示最左邊的圓柱。
# dst是大寫字母C,表示最右邊的圓柱。
# mid是大寫字母B,表示中間的圓柱。

count = 0

def hanoi (n, src, dst, mid):
    global count
    if n == 1:
        print("{}: {}->{}".format(1, src, dst))
        count += 1
    else:
    	hanoi(n-1,src,mid,dst)
    	count += 1
    	print(f"{count}:{src}->{dst}")
    	hanoi(n-1,mid,dst,src)


hanoi(3, "A", "C", "B")
print(count)
# 冪運算
# n:底數
# i:次數
def fn(n,i):
	if i == 1:
		return n
	else:
		return n*fn(n,i-1)

print(fn(2,3))
# 迴文串

def huiwen(str,beg,end):
	if beg==end:
		return True	
	if str[beg]!=str[end]:
		return False
	else:
		return huiwen(str,beg+1,end-1)

str = "abaa"
print(huiwen(str,0,len(str)-1))

def hui_wen(str):
	if len(str)<2:
		return True
	elif str[0] != str[-1]:
		return False
	return hui_wen(str[1:-1])

函數式編程

Python中,函數式一等對象

一等對象

  1. 對象是運行是創建
  2. 能賦值給變量或作爲數據結構中的元素
  3. 能作爲參數傳遞
  4. 能作爲返回值返回

高階函數

函數的函數

  1. 接收一個或多個函數作爲參數
  2. 將函數作爲返回值返回

函數作爲參數

def fn1(a):
	# 檢查是否爲偶數
	if a%2==0:
		return True
	else:
		return False
def fn5(a):
	# 檢查是否大於5
	if a > 5:
		return True
	else:
		return False
		
def fn(fnc,a):
	# 判斷a是否滿足fnc
	if fnc(a):
		return True
	else:
		return False

print(fn(fn5,1))
匿名函數(lambda)

創建一些簡單函數

語法
  • lambda 參數列表:返回值
def fn(a,b):
	return a+b

lambda a,b:a+b
fliter(fnc,iteSeq)

從序列中過濾出符合條件的元素,返回一個可迭代結構

map(fnc,iteSeq)

對可迭代元素做指定操作,添加到新對象中返回

print(map(lambda i:i+1,lst))
list.sort(fnc)

默認比較大小

  • 每次取列表中的一個元素作爲一個參數來調用函數
  • 使用函數返回值比較元素大小
  • key函數只在比較時起作用,不改變原數據
lst = ['a','bbb','a']

lst.sort(key=len)

print(lst)
sorted(seq,key=)

可對任意序列進行排列

  • 不影響原序列,返回新對象

閉包

將函數作爲返回值返回

  • 返回內部函數
  • 通過閉包創建只有當前函數可訪問的變量
  • 函數嵌套

裝飾器

通過裝飾器可以在不修改原函數情況下對函數進行擴展

def fn(old_fun):
	def new_fun(*args,**kwargs): 
		# *args接收所有位置參數
		# kwargs接收所有關鍵字參數
		print('開始執行')
		result = old_fun(*args,**kwargs)
		return result
	
	return new_fun

@fn
def old_fun():
	pass

# old_fun被裝飾
  • 通過@裝飾器,使用指定裝飾器
    • 可以同時爲一個函數指定多個裝飾器,函數 由內向外 裝飾器裝飾

OCP(開閉原則)

  • 開放對程序的擴展
  • 關閉對程序的修改

面向對象

類與對象

對象

內存中專門用於存儲數據的一塊區域

  1. 三部分
  • 對象的標識–id
  • 對象的類型–type
  • 對象的值–value

類(class)

對象是類的實例

  • 自定義類使用 大寫字母開頭
# 內置類創建

a = int(10) # create int object
b = str('hello') # create a string object
  • 創建自定義類
    • 語法:
class 類名([父類]):
	代碼塊

class Myclass():
	pass
  • 使用自定義類創建對象
class Myclass():
	pass

mc = Myclass()

對象的創建流程

類是用來創建對象的對象

  1. 創建變量
  2. 在內存中創建一個新對象
  3. 執行_init_()
  4. 將對象的id賦值給變量

類的定義

屬性+方法

  • 在類中定義的變量,將成爲所有實例的公共屬性

    • 公共屬性都可以被實例訪問
  • 類中定義的函數爲方法

    • 所有實例都可訪問類方法
    • 方法調用 默認傳遞一個參數,所以 方法 中至少有一個形參

屬性和方法

當調用一個對象的屬性時,解析器會現在當前對象中找是否有該屬性

  • 有,則直接返回對象的屬性值
  • 沒有,去類對象中找
    • 有,則返回類屬性
    • 無,報錯

類屬性(方法)

所有實例共享的屬性(方法)

實例屬性(方法)

某個實例特有的屬性(方法)

  • 一般情況下,屬性 保存在實例對象中
  • 方法保存在類對象中

self

本實例,相當於this

類init()

  • 特殊方法以 _ 開始和結束
  • 特殊方法不需要自己調用
_init()_在對象創建時執行

在新創建的對象初始化屬性

  • 通過self向新創建的對象初始化屬性
    • 作爲實例屬性
class Myclass:
	def _init_(self.name):
		self.name = name
  • 調用類創建對象時,參數列表中的參數會依次傳遞到init()中

類的基本結構

class 類名([父類]):
	公共屬性...
	
	# 對象初始化方法
	def _init_(self,...):
		...
	
	# 其他方法
	def method_1(self,...):
		...
	
	def method_2(self,...):
		...

類屬性

類屬性只能通過類方法修改,實例方法無法修改

實例屬性

實例屬性,只能通過實例方法訪問或修改的屬性,類方法無法修改

實例方法

第一個參數爲 self 的方法是實例方法
對象 作爲 self 傳入

  • 類和實例都可調用實例方法
    • 通過實例調用,將當前調用對象作爲 self 自動傳入
    • 通過類調用,不會自動傳遞當前對象,需手動傳入 實例
class A:
	pass
	
a = A()

a.test()

A.test(a)

類方法

使用 @classmethod 修飾的方法

  • 第一個參數爲 cls, 自動傳遞,
    • cls 表示當前類對象
class A:
	@classmethod
	def test(cls):
		print(cls)

  • 通過類和實例調用

靜態方法

類中 @staticmethod 修飾的方法

  • 不需要傳遞參數
  • 可通過類和實例調用

面向對象三大特性

1. 封裝

確保對象數據安全

隱藏對象中不希望被外部訪問的屬性或方法

  • 通過更換變量名,隱藏

  • 提供 gettersetter 外部可以訪問到屬性

    • getter 獲取對象中的指定屬性
      • get_屬性名()
    • setter 修改對象中的指定屬性
      • set_屬性名()
      • setter 中增加數據驗證,確保數據值的正確性
  • 一般情況 _屬性名 表示隱藏私有屬性

對象屬性前使用雙下劃綫

實際上將名字修改爲 __類名__屬性名

# __propertyName
class Person:
	def _init_(self,name):
		self.__name = name
	
	def get_name(self,name):
		return self.__name
	
	def set_name(self,name):
		self.__name = name
property裝飾器

property 裝飾器,將一個get方法轉換爲對象屬性

  • 使用 @property 方法,必須和屬性名一樣
    • setter裝飾器: @屬性名.setter
    • getter裝飾器: @property
  • 使用setter裝飾器 必須有 getter裝飾器
# @property
class Person:
	def _init_(self,name):
		self._name = name
	
	@property
	def name(self,name):
		return self._name
	
	@name.setter
	def name(self,name):
		self._name = name

p = Person('name1')
print(p.name)

2.繼承

保證對象的可擴展性

子類繼承父類中所有方法
包括特殊方法

  • _init_(self,name)
class 子類名([父類列表]):
	pass
  • 省略父類列表,默認爲父類 object
  • isinstance(instanceName,className)

檢查是否是某類的實例

  • issubclass(subClassName,className)

檢查是否爲子類

重寫(overwrite)

子類中有與父類同名方法,調用子類方法
包括特殊方法

  • _init_(self,name)
super()

調用父類方法修改父類屬性

  • 通過 super() 調用父類方法,不需要傳遞 self
def Subclass(SuperClass):
	def __init__(self,[Subclass propertyList]):
		super().__init__([SuperClass propertyList])
		self._propertyName = propertyVlue
className._bases_

獲取當前類的所有父類

多重繼承

爲一個類指定多個父類

  • 父類列表前面方法覆蓋後邊
    • 第一個父類
    • 第一個父類的父類
    • 第二個父類

3. 多態

保證程序的靈活性

不考慮參數類型,只要符合某些特徵,就可以使用方法

  1. len()
  • 只要對象中具有 _len_() 特殊方法,就可以通過 len() 方法獲取對象長度

垃圾回收

沒有引用的對象爲 垃圾

自動垃圾回收機制

不需要手動處理垃圾

  • 程序結束 時,自動刪除垃圾

_delete_(self)

在垃圾回收前刪除

特殊方法

__ 開頭和結尾

  • 配合多態使用
  • 特殊方法不需要手動調用

_new_(cls)

對象創建時調用

_init_(self)

對象初始化

_delete_(self)

對象刪除前調用

_str_(self)

** ** 打印的是__str()__的返回值

_repr_(self)

會對當前對象使用 repr() 時調用
指定對象在 交互模式(命令行) 中直接輸出的效果

_lt_(self,other)

小於

  • <

_le_(self,other)

小於等於

  • <=

_eq_(self,other)

等於

  • ==

_ne_(self,other)

不等於

  • !=

_gt_(self,other)

大於

_ge_(self,other)

大於等於

  • >=
# 定義 > < >= <= ==

class Person:
	def __lt__(self,other):
		return True

_add_(self,other)

_sub_(self,other)

_mul_(self,other)

_len(self)_

獲取對象長度

_bool(self)_

定義使用 bool() 返回值

模塊(module)

將一個完整程序分解爲一個個小模塊,將模塊組合,搭建一個完整程序

重要特性:複用

模塊創建

一個文件爲一個模塊

  • 模塊名要符合標識符規範
  • 在主模塊中相當於變量

引用外部模塊

  1. import 模塊名
    • 在多次引用同一個模塊,但只包含一個實例
  2. import 模塊名 as 別名

通過 moduleName._name_ 可以獲取模塊名字

  • 一個程序只有一個主模塊 _main_

包(package)

模塊中代碼過多,或一個模塊分解爲多個模塊

  • 包:文件夾

  • 模塊:.py文件

  • 包中必須有 _init_ 文件,包含包中主要內容

from packageName import moduleName:引入包中指定模塊

_pycache_:模塊緩存文件

使用包時將模塊代碼轉換爲機器碼,在編譯一次後,將代碼保存到緩存文件中,避免重複編譯

python標準庫

sys

提供變量和函數,可以獲取到Python解析器信息

或者通過函數操作解析器

import sys

# sys.argv
# 獲取執行代碼時,命令行所包含的參數
# 返回列表,保存當前命令的所有參數

# sys.modules
# 獲取當前程序中引入的所有模塊
# 返回字典,key:模塊名字,value:模塊內容

# sys.path
# 返回列表,保存模塊的搜索路徑
# 當前目錄優先

# sys.platform
# 表示當前Python運行平臺

# sys.exit()
# 退出當前程
pprint
import pprint

# pprint()
# 對打印數據做簡單格式化
# pprint.pprint()
os

操作系統模塊,對操作系統進行訪問

import os

# os.environ[]
# 獲取系統的環境

# os.system()
# 執行操作系統的命令
# os.system('dir')

異常

程序運行時:

使用沒有賦值變量
使用不存在索引值
除0

此時在異常處終止

處理異常

try:
	代碼塊(出現錯誤語句)
except:
	代碼塊(出現錯誤處理方式)
else:
	代碼塊(沒出錯執行語句)
finally:
	代碼塊(最後都會執行語句)

異常拋出

  1. 在函數中出現的異常進行處理,則不會繼續傳播
  2. 若未處理,繼續向調用處傳播,直到全局作用域
  3. 全局作用域爲處理,程序終止,顯示異常信息

  • 所有異常信息會被保存到異常對象中
  • 異常傳播是,將異常對象拋給調用處

異常對象

異常類 含義
ZeroDivisionError 表示除0異常
NameError 處理變量錯誤異常
IndexError 索引異常

捕獲異常對象

try:
	代碼塊
except 異常類型:
	# 加上異常類型,只捕獲特定類型異常
	代碼塊
except 異常類型:
	pass
except Exception as 異常名:
	# except後不加內容,捕獲到所有異常
	pass
finally:
	#無論是否出現異常,該子句都會執行
	pass

Exception

  • 所有異常的父類

語法

  • try必須有
  • except和finally至少有一個

自定義異常對象

  • 使用 raise 拋出異常

    • raise 異常類或異常實例(異常信息)
  • 所有異常都必須是 Exception 子類

class MyError(Exception):
	pass

文件

  • I/O(Input/Output)

文件操作步驟

  • 打開文件
  • 對文件進行操作
  • 保存
  • 關閉文件

打開文件

使用 open 函數打開文件

  • 返回一個代表打開文件的對象
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
  • file:要打開的文件路徑
    • 需要注意相對路徑與絕對路徑
    • Windows 下,可以用 / 代替 \
    • 或者使用 \\ 代替 \
    • 或者使用原始字符串 r"str"
    • 使用 返回上一級目錄
    • 如果目標文件距離當前文件較遠,使用絕對路徑
try:
    fileName = "demo.txt"
    fileObj = open(fileName)  # 打開fileName文件
    print(fileObj.read())

    fileObj.close()
except Exception as identifier:
    print('文件不存在')

關閉文件

  • close() 方法關閉文件
# with...as
with open(fileName) as file_obj:
	# 在with語句中可以直接使用file_obj做文件操作
	pass

文件讀取

  • read 方法用來讀取文件的內容,會將內容保存爲一個字符串返回
  • 默認爲純文本文件格式打開,編碼爲none
try:
    fileName = ''
    with open(fileName) as fileObj:
       content = fileObj.read()

       print(content)
except FileNotFoundError as identifier:
    print(f"{fileName}文件不存在")

讀取文件格式

  1. 純文本文件(使用utf-8編寫的文本文件)
  2. 二進制文件(圖片,mp3,ppt)

讀取中文文件

  • 指定文件編碼爲 utf-8
try:
    fileName = 'demo.txt'
    with open(fileName,encoding='utf-8') as fileObj:
       content = fileObj.read()

       print(content)
except FileNotFoundError as identifier:
    print(f"{fileName}文件不存在")

讀取大文件

  • read(size=-1)
    • 指定要讀字符數量,默認值爲-1,讀取文件中所有字符
    • 字符數量少於指定數量,全部讀出
    • read()會記錄上次讀取位置
    • 讀取到文件末尾,返回’’(空串)
try:
    fileName = 'demo.txt'
    with open(fileName,encoding='utf-8') as fileObj:
       chunk = 100
       fileContent = ""
       while True:
            content = fileObj.read(chunk)

            # 檢查是否讀取到了內容
            if not content:
                # 內容讀取完畢
                break

            fileContent+=content  
            print("本次讀取到的內容"+content,end="")
except FileNotFoundError as identifier:
    print(f"{fileName}文件不存在")

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-I7pJFfh6-1587303200322)(./1587300054150.png)]

readline()&readlines()

  1. readline() 讀取一行內容
  • readline() 自帶換行
  1. readlines()
  • 一次讀取到的內容返回,封裝到一個列表中返回
try:
    fileName = 'demo.txt'
    with open(fileName,encoding='utf-8') as fileObj:
       # readline() 讀取一行內容
       print(fileObj.readline())

       print(fileObj.readlines())
except FileNotFoundError as identifier:
    print(f"{fileName}文件不存在")

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-N2rTgUKO-1587303200325)(./1587300412647.png)]

直接遍歷文件對象

fileObj = open(fileName)
for t in fileObj:
	print(t)

文件寫入

write()

  • 使用 open() 打開文件,需要指定要做的操作
    • 不指定默認爲讀取文件
    • r:表示只讀
    • w:表示可寫
      • 文件不存在,創建文件
      • 文件存在,覆蓋原文件
    • a:表示追加內容
      • 文件不存在,創建內容
      • 文件存在,向文件追加內容
    • +:表示增加權限
      • r+: 即可讀又可寫,文件不存在報錯
      • w+
      • a+
    • x:用來新建文件
      • 不存在,則創建
      • 存在,則報錯
  • 寫入文本文件,傳遞一個字符串作爲參數
  • 返回寫入字符的個數
import pprint

try:
    fileName = 'demo.txt'
    with open(fileName,'w',encoding='utf-8',) as fileObj:
       # write()向文件寫入內容
       fileObj.write("Hello World\n")
       fileObj.write("Auspice Vinson")

    with open(fileName,'r',encoding="utf-8") as fileObj:
        for t in fileObj:
               print(t)
except FileNotFoundError as identifier:
    print(f"{fileName}文件不存在")

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jchZ91FD-1587303200329)(./1587301610953.png)]

二進制文件

**open()**參數

  • p
    • 讀取文本文件
  • b
    • 讀取二進制文件
    • 以字節讀取
# 讀取filename中的文件,寫入新對象中
with open(filename,'rb') as fileobj:
	with open(fileName,'wb') as fileObj:
		chunk = 1024*1024
		while True:
			content = fileObj.read(chunk)
			if not content:
				break
		
		fileObj.write(content)

seek()&tell()

  • fileObj.tell() 查看當前讀取位置
  • fileObj.seek() 切換讀取位置
    • arc1,切換的位置
    • arc2,計算位置方式
      • 0:從頭計算,默認
      • 1:從當前位置計算
      • 2:從最後位置開始計算

其他操作

  • 需要引入 os
import os

# 返回列表,元素爲目錄中每個文件名
r = os.listdir()

# 獲取當前所在的目錄
r = os.getcwd()

# 切換當前目錄 cd
r = os.chdir()

# 創建目錄
os.mkdir()

# 刪除目錄
os.rmdir()

# 刪除文件
os.remove()

# 重命名,移動文件
os.rename(oldName,newName)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章