首頁  >  文章  >  後端開發  >  總結Python編碼需要注意的地方

總結Python編碼需要注意的地方

零下一度
零下一度原創
2017-06-27 09:56:021194瀏覽


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


def pow_elem(x):
   """
   將x做乘運算子運算
   :param x:
#  :#:return:return: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中滿足函數返回True的值,組成新的sequence返回,如:
def is_odd(x):
   """
#判斷x是否為奇數
   :param x:
   :return:
   """
   return True if x % 2 > 0 else False

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

3) reduce(function, sequence)

reduce()函數接收的參數和map()類似,一個函數f,一個list,但行為和map()不同,reduce()傳入的函數f 必須接收兩個參數,reduce()對list的每個元素重複呼叫函數f,並傳回最終結果值。例如: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)都能實現三元運算, 但是2)較為少見,且不太優雅,同時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中,我們可以在函數內部定義函數並調用,如:
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")
輸出結果為:
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) 也可以將內部函數傳回,利用外部函數進行調用, 如:

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()呼叫傳回的是一個function對象,從if/else語句可以判斷出,回傳的是greet()函數,當我們呼叫hi()()時,其實是呼叫了內部函數greet()。

3)將函數作為參數傳遞給另一個函數, 如:

def hi():
   return "hi patty!"

def doSomethingBeforeHi(func):

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

doSomethingBeforeHi(hi)

輸出結果:
I ##doing someam
doing boring work before executing hi()
hi patty!
至此, 我們已經實作了一個簡單的裝飾器, 在呼叫hi()函數之前, 先輸出一行,實際應用中可能是一些預處理操作。實際上,裝飾器的功能就是在你的核心邏輯執行前後,加上一些通用的功能。

4) 簡單裝飾器的實作
def a_new_decorator(a_func):

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

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() smell")

a_function_requiring_decoration() #unction#out: "Iunction Iunction Iunction func. 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 w#Theunction(

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#acon smell working a_func()

5) 註解形式

@a_new_decorator
def b_function_requiring_decoration():
   print("I am the another function which needs some decoration to remove my am the another function which needs some decoration to remove my smul smell"
#b_function_requiring_decoration()

# I am doing some boring work before executing a_func()

# I am the another function which needs some decoupration to remove my foul smell#doboron smell#dobor aamration to remove my foul smell#. after executing a_func()
此處@a_new_decorator就等價於a_new_decorator(b_function_requiring_decoration)

#6) 取得name
對於4)中的a_function_requiring_decoration,__recon 得到的列印_confunction_requiring_decoration,__reconn_confunction_prints 的__結果是wrapTheFunction,而實際上我們希望得到的是a_func所對應的a_function_requiring_decoration函數名,Python為我們提供了wraps用來解決這個問題。

from functools import wraps

def a_new_decorator(a_func):
   @wraps(a_func)
   def wrapTheFunction():
100 50 月)

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":uth = {"username":
#」 "patty", "password": "123456"}
       if not check_auth(auth['username'], auth['password']):
     *kwargs)

def check_auth(username, password):
       print "Starting check auth..."

       return True if (username == 'patty' and password == '1234555 6') else False



   def authenticate():

       print "Already authenticate"

   return decorated

@requires_auth"##we lc 但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#unc
#_#)_funcf ):
   """Do some math."""
   return x + x

result = addition_func(4)

將會列印:addition_func was called

8)帶有參數的裝飾器
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"
. # Open the logfile and append

           with open( logfile, 'a') as opened_file:

               # Now we log to the specified logfile
         . _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_uncfile
##def __call__(self, funcfile

##def __call__( ##        with open(self.log_file, 'a') as fout:

     with open(self.log_file, 'a') as fout:

           log_msg = func.__name__ + " was c)    fout.write(os.linesep)

       # Now, send a notification
       self.notify()

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

class EmailLogit(Logit):
   '''
   A logit implementation for sending emails to admins
   when the function is cmplementation for sending emails to admins
   when the function is c家庭, email='admin@myproject.com'):
       self.email = email
       super(EmailLogit, self).__init__ Send an email to self.email
       # Will not be implemented here

       with open(self.log_file, 'a') as f:

    Do ##            f.write(os.linesep)
           f.write("Email has send to " + self.e )##  ("log1.txt")
def myfunc3():
   pass

@EmailLogit("log2.txt")
def myfunc4():
   pass

用類別作為裝飾器,我們的程式碼看起來更簡潔, 而且還可以透過繼承的方式,實現功能的個人化和重複使用。


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'}

在方法中,若傳入的參數採用可變型別並賦預設值,請注意會出現下列情況:

>>> 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]
這是因為, 預設參數在方法被定義時進行計算,而不是每次呼叫時再計算一次。因此, 為了避免上述情況, 當我們預期每次方法被呼叫時,以一個新的空列表進行計算的時候,可採取如下寫法:
>>> 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中,物件的賦值,拷貝(深/淺拷貝)之間是有差異的,如果使用的時候不注意,就可能產生意外的結果。
1) Python中預設是淺拷貝方式
>>> foo = ['hi']
>>> bar = foo
>>> id (foo)
4458211232
>>> id(bar)    

4458211232

>>> bar.append("patty")
>>>> bar.append("patty")
>>> bar
['hi', 'patty']
>>> foo
#['hi', 'patty']
注意:id(foo)==id(bar) ,說明foo和bar引用的是同一個對象, 當透過bar引用對list進行append操作時, 由於指向的是同一塊記憶體空間,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的深拷貝,實際上是在內存中新開了一片空間,將foo對象所引用的內容複製到新的內存空間中,因此當對slow對象所引用的內容進行update操作後,更改只體現在slow物件的引用上,而foo物件所引用的內容並沒有改變。

6、集合Collection
1) defaultdict
對於普通的dict,若是取得不存在的key,會引發KeyError錯誤,如下:
some_dict = {}
some_dict['colours' ]['favourite'] = "yellow"
# Raises KeyError: 'colours'
但是透過defaultdict,我們可以避免這種情況的發生, 如下:
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,可以統計出特定項目的出現次數,如:
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可以設定佇列的最大長度,當元素數目超過最大長度時,會從目前帶插入方向的反方向刪除對應數目的元素,如下:
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:
     print('exception')
else:
   # anycode  # 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 comcurs. And an  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之前執行。


10、內建方法
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語句的正常結束方式有兩種:一是滿足特定條件的情況下break跳出循環,二是所有條件循環結束。 for-else中的else語句只有在所有條件都經過判斷然後正常結束for循環的情況下,才被執行,如下:
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+的環境中引用Python 3+的模組
2)相容的模組導入方式
try:
   import urllib。 #

以上是總結Python編碼需要注意的地方的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn