最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

總結(jié)Python編碼需要注意的地方

來源:懂視網(wǎng) 責編:小采 時間:2020-11-27 14:23:48
文檔

總結(jié)Python編碼需要注意的地方

總結(jié)Python編碼需要注意的地方:1、map, filter, reduce1) map(func, input_list)將函數(shù)應用到輸入列表上的每個元素, 如:input_list = [1, 2, 3, 4, 5]def pow_elem(x): """ 將x做乘方運算 :param x: :return: ""&q
推薦度:
導讀總結(jié)Python編碼需要注意的地方:1、map, filter, reduce1) map(func, input_list)將函數(shù)應用到輸入列表上的每個元素, 如:input_list = [1, 2, 3, 4, 5]def pow_elem(x): """ 將x做乘方運算 :param x: :return: ""&q

1、map, filter, reduce
1) map(func, input_list)
將函數(shù)應用到輸入列表上的每個元素, 如:
input_list = [1, 2, 3, 4, 5]


def pow_elem(x):
"""
將x做乘方運算
:param x:
:return:
"""
return x * x


def multi_x_y(x, y):
return x * y


print map(pow_elem, input_list) # output:[1, 4, 9, 16, 25]

print map(multi_x_y, input_list, input_list) # output:[1, 4, 9, 16, 25]

2) filter(func_or_none, sequence)
過濾篩選出sequence中滿足函數(shù)返回True的值,組成新的sequence返回,如:
def is_odd(x):
"""
判斷x是否為奇數(shù)
:param x:
:return:
"""
return True if x % 2 > 0 else False

print filter(is_odd, input_list) # output: [1, 3, 5]

3) reduce(function, sequence)
reduce()函數(shù)接收的參數(shù)和 map()類似,一個函數(shù) f,一個list,但行為和 map()不同,reduce()傳入的函數(shù) f 必須接收兩個參數(shù),reduce()對list的每個元素反復調(diào)用函數(shù)f,并返回最終結(jié)果值。例如:reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 等價于((((1+2)+3)+4)+5)
print reduce(lambda x, y: x * y, input_list) # output: 120

2、三元運算
下面兩種寫法等價:
"Yes" if 2==2 else "No"
("No", "Yes")[2==2]
即:
1) condition_is_true if condition else condition_is_false
2) (if_test_is_false, if_test_is_true)[test]
1)和2)都能實現(xiàn)三元運算, 但是2)較為少見,且不太優(yōu)雅,同時2)并不是一個短路運算,如下:
5 if True else 5/0 # output: 5
(1/0, 5)[True] # throw exception-> ZeroDivisionError: integer division or modulo by zero

3、裝飾器
1) Python中,我們可以在函數(shù)內(nèi)部定義函數(shù)并調(diào)用,如:
def hi(name="patty"):
print("now you are inside the hi() function")

def greet():
return "now you are in the greet() function"

def welcome():
return "now you are in the welcome() function"

print(greet())
print(welcome())
print("now you are back in the hi() function")
輸出結(jié)果為:
now you are inside the hi() function
now you are in the greet() function
now you are in the welcome() function
now you are back in the hi() function

2) 也可以將內(nèi)部函數(shù)返回,利用外部函數(shù)進行調(diào)用, 如:
def hi(name="patty"):
def greet():
return "now you are in the greet() function"

def welcome():
return "now you are in the welcome() function"

return greet if name == 'patty' else welcome


print hi() # <function greet at 0x109379a28>
print hi()() # now you are in the greet() function
上述代碼中,hi()調(diào)用返回的是一個function對象,從if/else語句中可以判斷出,返回的是greet()函數(shù),當我們調(diào)用hi()()時,實際上是調(diào)用了內(nèi)部函數(shù)greet()。

3)將函數(shù)作為參數(shù)傳遞給另一個函數(shù), 如:
def hi():
return "hi patty!"

def doSomethingBeforeHi(func):
print("I am doing some boring work before executing hi()")
print(func())

doSomethingBeforeHi(hi)
輸出結(jié)果:
I am doing some boring work before executing hi()
hi patty!
至此, 我們已經(jīng)實現(xiàn)了一個簡單的裝飾器, 在調(diào)用hi()函數(shù)之前, 先輸出一行,實際應用中可能是一些預處理操作。實際上,裝飾器的功能就是在你的核心邏輯執(zhí)行前后,加上一些通用的功能。

4) 簡單裝飾器的實現(xiàn)
def a_new_decorator(a_func):

def wrapTheFunction():
print("I am doing some boring work before executing a_func()")

a_func() # call this function

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")

a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()

a_function_requiring_decoration()
# I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()

5) 注解形式
@a_new_decorator
def b_function_requiring_decoration():
print("I am the another function which needs some decoration to remove my foul smell")

b_function_requiring_decoration()
# I am doing some boring work before executing a_func()
# I am the another function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
此處@a_new_decorator就等價于a_new_decorator(b_function_requiring_decoration)

6) 獲取name
對于4)中的a_function_requiring_decoration, 我們打印print(a_function_requiring_decoration.__name__) 得到的結(jié)果是wrapTheFunction,而實際上我們希望得到的是a_func所對應的a_function_requiring_decoration函數(shù)名,Python為我們提供了wraps用來解決這個問題。
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")

a_func()

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

7) 裝飾器的一些應用場景
用戶認證
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = {"username": "patty", "password": "123456"}
if not check_auth(auth['username'], auth['password']):
authenticate()
return f(*args, **kwargs)

def check_auth(username, password):
print "Starting check auth..."
return True if (username == 'patty' and password == '123456') else False


def authenticate():
print "Already authenticate"
return decorated

@requires_auth
def welcome():
return "Welcome patty!"

print welcome()

日志記錄
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging

@logit
def addition_func(x):
"""Do some math."""
return x + x


result = addition_func(4)
將會打?。篴ddition_func was called

8)帶參數(shù)的裝飾器
from functools import wraps

def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# Open the logfile and append
with open(logfile, 'a') as opened_file:
# Now we log to the specified logfile
opened_file.write(log_string + ' ')
return wrapped_function
return logging_decorator

@logit()
def myfunc1():
pass

myfunc1()
# Output: myfunc1 was called
# A file called out.log now exists, with the above string

@logit(logfile='func2.log')
def myfunc2():
pass

myfunc2()

9) 用類作為裝飾器
import os
class Logit(object):
def __init__(self, log_file):
self.log_file = log_file

def __call__(self, func):
with open(self.log_file, 'a') as fout:
log_msg = func.__name__ + " was called"
fout.write(log_msg)
fout.write(os.linesep)
# Now, send a notification
self.notify()

def notify(self):
# logit only logs, no more
pass

class EmailLogit(Logit):
'''
A logit implementation for sending emails to admins
when the function is called.
'''
def __init__(self, log_file, email='admin@myproject.com'):
self.email = email
super(EmailLogit, self).__init__(log_file)

def notify(self):
# Send an email to self.email
# Will not be implemented here
with open(self.log_file, 'a') as f:
f.write("Do Something....")
f.write(os.linesep)
f.write("Email has send to " + self.email)
f.write(os.linesep)


@Logit("log1.txt")
def myfunc3():
pass

@EmailLogit("log2.txt")
def myfunc4():
pass
用類作為裝飾器,我們的代碼看上去更簡潔, 而且還可以通過繼承的方式,實現(xiàn)功能的個性化和復用。

4、可變類型
Python中的可變類型包括列表和字典,這些對象中的元素是可改變的,如
>>> foo = ['hi']
>>> foo += ['patty']
>>> foo
['hi', 'patty']
>>> foo[0]='hello'
>>> foo
['hello', 'patty']

>>> fdict = {"name":"patty"}
>>> fdict.update({"age":"23"})
>>> fdict
{'age': '23', 'name': 'patty'}
>>> fdict.update({"age":"25"})
>>> fdict
{'age': '25', 'name': 'patty'}

在方法中,若傳入的參數(shù)采用可變類型并賦默認值,要注意會出現(xiàn)以下情況:
>>> def add_to(num, target=[]):
... target.append(num)
... return target
...
>>> add_to(1)
[1]
>>> add_to(2)
[1, 2]
>>> add_to(3)
[1, 2, 3]
這是因為, 默認參數(shù)在方法被定義時進行計算,而不是每次調(diào)用時再計算一次。因此, 為了避免出現(xiàn)上述情況, 當我們期待每次方法被調(diào)用時,以一個新的空列表進行計算的時候,可采取如下寫法:
>>> def add_to(num, target=None):
... if target is None:
... target = []
... target.append(num)
... return target
...
>>> add_to(1)
[1]
>>> add_to(2)
[2]

5、淺拷貝和深拷貝
Python中,對象的賦值,拷貝(深/淺拷貝)之間是有差異的,如果使用的時候不注意,就可能產(chǎn)生意外的結(jié)果。
1) Python中默認是淺拷貝方式
>>> foo = ['hi']
>>> bar = foo
>>> id(foo)
4458211232
>>> id(bar)
4458211232
>>> bar.append("patty")
>>> bar
['hi', 'patty']
>>> foo
['hi', 'patty']
注意:id(foo)==id(bar),說明foo和bar引用的是同一個對象, 當通過bar引用對list進行append操作時, 由于指向的是同一塊內(nèi)存空間,foo的輸出與bar是一致的。

2) 深拷貝
>>> foo
['hi', {'age': 20, 'name': 'patty'}]
>>> import copy
>>> slow = copy.deepcopy(foo)
>>> slow
['hi', {'age': 20, 'name': 'patty'}]
>>> slow[0]='hello'
>>> slow
['hello', {'age': 20, 'name': 'patty'}]
>>> foo
['hi', {'age': 20, 'name': 'patty'}]
注意: 由于slow是對foo的深拷貝,實際上是在內(nèi)存中新開了一片空間,將foo對象所引用的內(nèi)容復制到新的內(nèi)存空間中,因此當對slow對像所引用的內(nèi)容進行update操作后,更改只體現(xiàn)在slow對象的引用上,而foo對象所引用的內(nèi)容并沒有發(fā)生改變。

6、集合Collection
1) defaultdict
對于普通的dict,若是獲取不存在的key,會引發(fā)KeyError錯誤,如下:
some_dict = {}
some_dict['colours']['favourite'] = "yellow"
# Raises KeyError: 'colours'
但是通過defaultdict,我們可以避免這種情況的發(fā)生, 如下:
import collections
import json
tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"
print json.dumps(some_dict)
# Works fine, output: {"colours": {"favourite": "yellow"}}

2) OrderedDict
OrderedDict能夠按照我們定義字典時的key順序打印輸出字典,改變value的值不會改變key的順序, 但是,對key進行刪除,重新插入后,key會重新排序到dict的尾部。
from collections import OrderedDict

colours = OrderedDict([("Red", 198), ("Green", 170), ("Blue", 160)])
for key, value in colours.items():
print(key, value)

3)Counter
利用Counter,可以統(tǒng)計特定項的出現(xiàn)次數(shù),如:
from collections import Counter

colours = (
('Yasoob', 'Yellow'),
('Ali', 'Blue'),
('Arham', 'Green'),
('Ali', 'Black'),
('Yasoob', 'Red'),
('Ahmed', 'Silver'),
)

favs = Counter(name for name, colour in colours)
print(favs)
# Counter({'Yasoob': 2, 'Ali': 2, 'Arham': 1, 'Ahmed': 1})

4)deque
deque是一個雙端隊列,可在頭尾分別進行插入,刪除操作, 如下:
from collections import deque
queue_d = deque()
queue_d.append(1)
queue_d.append(2)
print queue_d # deque([1, 2])
queue_d.appendleft(3)
print queue_d # deque([3, 1, 2])

queue_d.pop()
print queue_d # deque([3, 1])
queue_d.popleft()
print queue_d # deque([1])

deque可以設置隊列的最大長度,當元素數(shù)目超過最大長度時,會從當前帶插入方向的反方向刪除相應數(shù)目的元素,如下:
queue_c = deque(maxlen=5, iterable=[2, 4, 6])
queue_c.extend([7, 8])
print queue_c # deque([2, 4, 6, 7, 8], maxlen=5)
queue_c.extend([10, 12])
print(queue_c) # deque([6, 7, 8, 10, 12], maxlen=5)
queue_c.extendleft([18])
print(queue_c) # deque([18, 6, 7, 8, 10], maxlen=5)

5)nametuple
tuple是不可變的列表,不可以對tuple中的元素重新賦值,我們只能通過index去訪問tuple中的元素。nametuple可看做不可變的字典,可通過name去訪問tuple中的元素。如:
from collections import namedtuple

Animal = namedtuple('Animal', 'name age type')
perry = Animal(name="perry", age=31, type="cat")

print(perry)
# Output: Animal(name='perry', age=31, type='cat')

print(perry.name)
# Output: 'perry'

print(perry[0])
# Output: 'perry'

print(perry._asdict())
# Output: OrderedDict([('name', 'perry'), ('age', 31), ('type', 'cat')])

7、Object introspection
1) dir: 列舉該對象的所有方法
2)type: 返回對象的類型
3)id: 返回對象的id

8、生成器
1)list
>>> squared = [x**2 for x in range(10)]
>>> squared
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
2) dict
{v: k for k, v in some_dict.items()}
3) set
>>> squared = {x**2 for x in range(10)}
>>> squared
set([0, 1, 4, 81, 64, 9, 16, 49, 25, 36])

9、異常處理
try:
print('I am sure no exception is going to occur!')
except Exception:
print('exception')
else:
# any code that should only run if no exception occurs in the try,
# but for which exceptions should NOT be caught
print('This would only run if no exception occurs. And an error here '
'would NOT be caught.')
finally:
print('This would be printed in every case.')

# Output: I am sure no exception is going to occur!
# This would only run if no exception occurs.
# This would be printed in every case.
else中的語句會在finally之前執(zhí)行。

10、內(nèi)置方法
a_list = [[1, 2], [3, 4], [5, 6]]
print(list(itertools.chain.from_iterable(a_list)))
# Output: [1, 2, 3, 4, 5, 6]

# or
print(list(itertools.chain(*a_list)))
# Output: [1, 2, 3, 4, 5, 6]


class A(object):
def __init__(self, a, b, c, d, e, f):
self.__dict__.update({k: v for k, v in locals().items() if k != 'self'})

11、for-else語句
for語句的正常結(jié)束方式有兩種:一是在滿足特定條件的情況下break跳出循環(huán),二是所有條件循環(huán)結(jié)束。 for-else中的else語句只有在所有條件都經(jīng)過判斷然后正常結(jié)束for循環(huán)的情況下,才被執(zhí)行,如下:
for x in range(1, 10, 2):
if x % 2 == 0:
print "found even of %d"%x
break
else:
print "not foud even"
# output: not foud even

12、兼容Python 2+和Python 3+
1) 利用 __future__模塊在Python 2+的環(huán)境中引用Python 3+的模塊
2)兼容的模塊導入方式
try:
import urllib.request as urllib_request # for Python 3
except ImportError:
import urllib2 as urllib_request # for Python 2

Reference:

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

總結(jié)Python編碼需要注意的地方

總結(jié)Python編碼需要注意的地方:1、map, filter, reduce1) map(func, input_list)將函數(shù)應用到輸入列表上的每個元素, 如:input_list = [1, 2, 3, 4, 5]def pow_elem(x): """ 將x做乘方運算 :param x: :return: ""&q
推薦度:
標簽: 代碼 的地方 編碼
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top