python代碼規(guī)范之異常,規(guī)則,函數(shù)返回值使用解讀
一:python的規(guī)則
1:集合的規(guī)則
- 規(guī)則: 如果要把一個東西裝到集合中去,這個東西必須是可以哈希的。
- 可變類型都是不可哈希的。(列表, 集合,字典),本質(zhì)就是哈希值不固定。
- 思維1: 對于存在A,不存在B等問題,思維定式就是采用集合思維處理。
- 思維2: 我們可以自定義哈希對象。
案例:
給定兩個列表套字典的數(shù)據(jù),數(shù)據(jù)內(nèi)容是人員(姓名,電話相同,則默認就是同一個人),我們要求是找出存在A列表,但是不存在B列表的人員。
list_a = [
{'first_name': 'Ren', 'last_name': 'shanshan', 'phone_num': '12345678'},
{'first_name': 'Wang', 'last_name': 'gang', 'phone_num': '12323338'},
{'first_name': 'Li', 'last_name': 'ruixue', 'phone_num': '123389278'},
]
list_b = [
{'first_name': 'Ren', 'last_name': 'shanshan', 'phone_num': '12345678'},
{'first_name': 'Wang', 'last_name': 'gang', 'phone_num': '12323338'},
{'first_name': 'Xu', 'last_name': 'daer', 'phone_num': '125545678'},
]
class People(object):
def __init__(self, first_name, last_name, phone_num):
self.first_name = first_name
self.last_name = last_name
self.phone_num = phone_num
def __hash__(self):
# 默認是內(nèi)存地址的哈希,這里我們改成名字+電話這樣的一個元組的哈希值。
return hash(
(self.first_name, self.last_name, self.phone_num)
)
def __eq__(self, other):
# 如果傳入的對象是當前類的對象,并且哈希值兩者相等,則返回True。
if isinstance(other, People) and hash(other) == hash(self):
return True
return False
# 將字典構(gòu)造成哈希對象,然后加入集合中
set_1 = set(People(**p) for p in list_a)
set_2 = set(People(**p) for p in list_b)
# 使用集合的差
end_set = set_1 - set_2
for item in end_set:
print(item.first_name, item.last_name, item.phone_num)
# Li ruixue 123389278
使用python3.7版本之后的數(shù)據(jù)類: dataclasses。
from dataclasses import dataclass
@dataclass(unsafe_hash=True)
class People(object):
first_name: str
last_name: str
phone_num: str
set_1 = set(People(**p) for p in list_a)
set_2 = set(People(**p) for p in list_b)
end_set = set_1 - set_2
for item in end_set:
print(item.first_name, item.last_name, item.phone_num)
# Li ruixue 123389278
2:__format__對象字符串格式化
1: 需求: 對于自己定義的People對象,打印出不同的信息。
class People(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __format__(self, format_spec):
if format_spec == 'long':
return f'{self.name} is {self.age} years old!'
elif format_spec == 'simple':
return f'{self.name} ({self.age})'
raise ValueError('invalid format spec')
p = People(name='liangshan', age=23)
print('{0:simple}'.format(p))
# liangshan (23)
print('{0:long}'.format(p))
# liangshan is 23 years old!
3:__getitem__方法定義容器
1: 如果我想定義一個容器,那么肯定要考慮的就是容器取長度的方法,容器取第幾個元素方法。
class Events:
def __init__(self, events):
self.events = events
def __len__(self):
"""自定義長度,將會被用來做布爾判斷"""
return len(self.events)
def __getitem__(self, index):
"""自定義切片方法"""
# 直接將 slice 切片對象透傳給 events 處理
return self.events[index]
events = Events([
'computer started',
'os launched',
'docker started',
'os stopped',
])
# 理解: if events 對調(diào)用里面的__len__方法,通過返回是否是0來判斷是否是None
# events使用切片的時候,會調(diào)用events的__getitem__方法,
# 而我們直接調(diào)用self的切片操作,相當于又調(diào)用了list中的__getitem__方法。也就是說
# 只要是實例化Events的時候,是可以使用切片的,則這個類的對象也是可以使用切片的。
if events:
print(events[1:3])
二:python異常處理三個習慣
1: 只做最精準的異常捕獲,每個異常捕獲只處理一個容易錯的地方。
2:避免拋出高于當前抽象級別的異常外,我們同樣應(yīng)該避免泄露低于當前抽象級別的異常。
3:連續(xù)異常,注意使用上下文管理器。
def upload_avatar(request):
"""用戶上傳新頭像"""
try:
avatar_file = request.FILES['avatar']
except KeyError:
raise error_codes.AVATAR_FILE_NOT_PROVIDED
try:
resized_avatar_file = resize_avatar(avatar_file)
except FileTooLargeError as e:
raise error_codes.AVATAR_FILE_TOO_LARGE
except ResizeAvatarError as e:
raise error_codes.AVATAR_FILE_INVALID
try:
request.user.avatar = resized_avatar_file
request.user.save()
except Exception:
raise error_codes.INTERNAL_SERVER_ERROR
return HttpResponse({})
下面代碼連續(xù)的異常,讓我們看到眼花繚亂。
使用上下文管理器管理異常:
class Resource(object):
def __enter__(self):
print("連接資源")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("關(guān)閉資源")
return True
def operate(self):
1 / 0
with Resource() as res:
res.operate()
# 不會報錯
- 什么是上下文管理器?
- 答: 一個類實現(xiàn)了
__enter__方法和__exit__方法,則這個類的實例就是上下文管理器。 - 上下文管理器的強大在于
__exit__中你可以決定是拋出異常還是在這里解決。
三:函數(shù)返回建議
1: 單個函數(shù),返回值不要有多種類型。
2: partial函數(shù)構(gòu)造函數(shù):
def multiply(x, y):
return x * y
def double(value):
# 返回另一個函數(shù)調(diào)用結(jié)果
return multiply(2, value)
from functools import partial
# partial函數(shù)是專門用來基于一個函數(shù)來構(gòu)造一個新的函數(shù)的。
# 參數(shù)1: 函數(shù)名
# 其余參數(shù)就是被基于的函數(shù)的參數(shù)。
def multiply(x, y):
return x * y
double = partial(multiply, 2)
3: 不要返回結(jié)果和錯誤,而是選擇拋出異常。
4:謹慎使用None返回:
- None作為默認返回值(沒有問題)
- None作為意料之中的返回值(沒有問題)
- None作為調(diào)用失敗返回值, 不推薦使用,更改為異常捕獲方式。
5:合理返回空對象:
- 對于返回為None的地方,我們在接受返回值的地方就要使用異常捕獲,判斷是否為None,這非常的麻煩。
- Django 框架里的 AnonymousUser 就是一個典型的 null object。
原理:
就是使用一個符合正常結(jié)果接口的“空類型”來替代空值返回/拋出異常,以此來降低調(diào)用方處理結(jié)果的成本。
案例:
class Account:
# def __init__ 已省略... ...
@classmethod
def from_string(cls, s):
"""從字符串初始化一個賬號
:returns: 如果輸入合法,返回 Account object,否則返回 NullAccount
"""
try:
username, balance = s.split()
balance = decimal.Decimal(float(balance))
except ValueError:
return NullAccount()
if balance < 0:
return NullAccount()
return cls(username=username, balance=balance)
class NullAccount:
username = ''
balance = 0
@classmethod
def from_string(cls, s):
raise NotImplementedError
6:返回生成器,而不是返回列表。
# 返回列表
def test01(my_list):
res_list = []
for item in my_list:
res_list.append(item * 2)
return res_list
# 返回生成器
def test02(my_list):
for item in my_list:
yield item * 2
my_list = [1, 2, 3, 4, 5]
print(test01(my_list))
# [2, 4, 6, 8, 10]
print(test02(my_list))
# <generator object test02 at 0x000001A6C693A2A0>
for item in test02(my_list):
print(item)
7:盡量不要使用遞歸:
- python不支持尾遞歸優(yōu)化。
- python遞歸有最大層數(shù)限制。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python實用小技巧之判斷輸入是否為漢字/英文/數(shù)字
這篇文章主要給大家介紹了關(guān)于Python實用小技巧之判斷輸入是否為漢字/英文/數(shù)字的相關(guān)資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2023-06-06
如何使用Python生成4位數(shù)的隨機數(shù)字
本文討論了如何使用randint() 和randrange() 方法來生成一個四位數(shù)的數(shù)字,此外,我們還討論了另一種擁有隨機四位數(shù)號碼的途徑,感興趣的朋友跟隨小編一起看看吧2023-10-10
使用 Python ssh 遠程登陸服務(wù)器的最佳方案
這篇文章主要介紹了使用 Python ssh 遠程登陸服務(wù)器的最佳方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03
Python爬蟲實現(xiàn)selenium處理iframe作用域問題
這篇文章主要介紹了Python爬蟲實現(xiàn)selenium處理iframe作用域問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01
python基礎(chǔ)之Numpy庫中array用法總結(jié)
NumPy(Numerical Python的縮寫)是一個開源的Python科學計算庫,使用NumPy就可以很自然地使用數(shù)組和矩陣,這篇文章主要給大家介紹了關(guān)于python基礎(chǔ)之Numpy庫中array用法的相關(guān)資料,需要的朋友可以參考下2021-08-08

