標籤:

Python 開發中有哪些高級技巧?


謝謝老原 @原博文 邀請 : )

我列出來幾個,不知道算不算高級技巧,但是我個人覺得非常有用。

1. 善用迭代器

迭代器在很多語言裡面都有,而在 Python 里適當的場景用迭代器會非常的「爽」。一來因為迭代器每次產生一個對象,適當使用能有效節省內存;二來它能達到部分「延遲計算」的效果。除此以外,因為 Generator (yield 關鍵字)和 Generator Expression 的存在,有時候使用迭代器能提升代碼可讀性。

舉例,itertools.islice((calculate_for_value(v) for v in values), 0, 12) 能夠只在 [0, 12) 範圍內計算,而且是延遲計算的,即迭代到了那個對象才去計算。又如 any(i % 3 == 0 for i in numbers) 能夠找出 numbers 里第一個能被 3 整除的值,因為裡面是個 Generator Expression(迭代器的一種),所以找出以後 any 函數就會立即返回,並不需要對整個 numbers 列表計算 i % 3。

順帶推薦下這個庫 erikrose/more-itertools ,裡面包含了很多實用的迭代器函數,是對標準庫 itertools 的一個很不錯的補充。

2. 善用描述符(Descriptor)

Python 的描述符是對「屬性」的抽象,一個描述符定義成類屬性以後,能夠控制這個類的實例上同名實例屬性的 get、set、delete 行為,比 __getattr__ 這樣的實例級 magic method 有更細的粒度,並且更容易復用。這個文檔有簡單的描述 Descriptor HowTo Guide ,可見 Python 的「實例方法」、@property 全由它實現,一些第三方庫也有用到(例如 SQLAlchemy 的 Column、WTForms 的 Field 乃至 Python 3.4 新增的 enum.Enum 類型)。

利用描述符特性,可以在業務代碼中實現一些非常方便的定製,例如可以自己實現一個能緩存返回值的 cached_property(也可以不用自己實現,直接用 Werkzeug 的)。

3. 盡量不要用反射技巧去 fight with language

我個人的一個觀點:用一門編程語言就應該入鄉隨俗,fight with language 的事情不要做太多為好。因為閉門造的輪子很難造圓,更何況站在語言使用者的層面去和語言的設計搏擊實在很不自量力。

問題問的是「高級技巧」,那麼對於一個動態語言,反射當然算高級技巧的。可是我見過一些利用 Python 的反射來掃描出一些包中所有 .py 文件然後自動 import 包下的所有模塊的。且不說這個做法破壞了 Python 「模塊即是命名空間」 和 lazy import 的設定,光是從「正確性」來說就有一堆問題。這個做法僅僅考慮到了模塊文件系統中的場景,沒考慮到可能模塊在一個 zip 中的情況。就算再增強一下實現,考慮上 zip 的 import,那 Python 還有 PEP 302 定義的 Import Hook 用法呢,被這樣一 hack 就完全沒法用了。這種 fight with language 的做法很難去做到真正的「正確」。

所以我覺得還有一個 Python 的技巧就是想使用「高級技巧」的時候謹慎地考慮使用。靜下來想想自己是不是在 fight with language 了,如果是的話,建議停手。要不就入鄉隨俗,要不就認真考慮一下 Python 是不是真的有值得去改進的地方。後者是需要經過很多深思熟慮的,不是 10 分鐘的想法就夠。如果後者的回答真的是「是」,我想可能正確的做法是寫一個 PEP 然後和社區討論,看能否將改進直接施於 Python 未來的版本之上,而不是在自己的代碼里用一個看似高級技巧實是醜陋的 hack 的實現來對抗語言本身。

-------------------------------------------------------------------------------

其他的一些 Python 特色的技巧,例如 decorator、contextmanager 等,因為各路 Python 開發者基本都很熟悉,我就沒列出來了。

-------------------------------------------------------------------------------

補充下:其實這裡有個超長列表 Hidden features of Python …… 不過裡面的很多特性現在都是日常了

-------------------------------------------------------------------------------

2016-10-08 補充:來個真的有點高(黑)級(暗)的技巧吧,開發一個 stateful service 的時候怎麼排障?比如出現死鎖了,或者某個線程意外退出。這個時候可以從

gc.get_objects()

掏出所有活著的對象,其中當然就包括活著的線程。

例如,列印出所有 Greenlet 的 stack:

import os
import gc
import greenlet
import traceback

greenlets = [
o for o in gc.get_objects() if isinstance(o, greenlet.greenlet) if o]
stack = "

".join(
"".join(traceback.format_stack(o.gr_frame)) for o in greenlets)
open("/tmp/stack-%d.txt" % os.getpid(), "w").write(stack)

這個方法結合 gevent.backdoor 堪稱排障利器。如果願意冒一定的風險,甚至可以使用調試器對事先沒有埋過點的進程做活體檢測——掛上 GIL 再列印一份線程 stack。詳見 GitHub - wooparadog/pstack: Tool to dump python thread and greenlet stacks.


我也列(zhuang)出(bi)幾個高級技巧:

1. contextmanager

寫Python代碼的時候經常將一系列操作放在一個語句塊中,Python 2.5加入了with語法,實現上下文管理功能,這讓代碼的可讀性更強並且錯誤更少。最常見的例子就是open,如果不使用with,使用open會是這樣:

In : f = open("/tmp/a", "a")
In : f.write("hello world")
In : f.close()

如果使用with,可以簡化為兩行:

In : with open("/tmp/a", "a") as f:
....: f.write("hello world")
....:

在執行完縮進的代碼塊後會自動關閉文件。創建上下文管理器實際就是創建一個類,添加__enter__和__exit__方法。看看如何實現open的上下文管理功能:

class OpenContext(object):

def __init__(self, filename, mode):
self.fp = open(filename, mode)

def __enter__(self):
return self.fp

def __exit__(self, exc_type, exc_val, exc_tb):
self.fp.close()

with OpenContext("/tmp/a", "a") as f:
f.write("hello world")

自定義上下文管理器確實很方便,但是Python標準庫還提供了更易用的上下文管理器工具模塊contextlib,它是通過生成器實現的,我們不必再創建類以及__enter__和__exit__這兩個特殊的方法:

from contextlib import contextmanager

@contextmanager
def make_open_context(filename, mode):
fp = open(filename, mode)
try:
yield fp
finally:
fp.close()

with make_open_context("/tmp/a", "a") as f:
f.write("hello world")

yield關鍵詞把上下文分割成兩部分:yield之前就是__init__中的代碼塊;yield之後其實就是__exit__中的代碼塊;yield生成的值會綁定到with語句as子句中的變數(如果沒有生成,也就沒有as字句)。

2. total_ordering。對比自定義對象需要添加__lt__、__le__、__gt__、__ge__和__eq__等方法,如果使用total_ordering,只需要定義__eq__以及__lt__、__le__、__gt__、__ge__四種之一就可以了:

In : @functools.total_ordering
...: class Size(object):
...: def __init__(self, value):
...: self.value = value
...: def __lt__(self, other):
...: return self.value &< other.value ...: def __eq__(self, other): ...: return self.value == other.value In : Size(3) &> Size(2)
Out: True
In : Size(2) == Size(2)
Out: True

3. 有時候BUG隱藏的太深,需要對上下文都有清晰的展示來幫助判斷。用pdb調試不方便,用print不直觀。可以使用如下函數獲取當前調用棧:

import sys

def get_cur_info():
print sys._getframe().f_code.co_filename # 當前文件名
print sys._getframe(0).f_code.co_name # 當前函數名
print sys._getframe(1).f_code.co_name # 調用該函數的函數的名字,如果沒有被調用,則返回module
print sys._getframe().f_lineno # 當前行號

4. inspect。有時候我們想查看一下對象的一些信息或者做類型檢查,也就是自省(檢查某些事物以確定它是什麼、它知道什麼以及它能做什麼):

In : def add(a, b=1):
...: return a + b
...:

In : inspect.getsourcelines(add)
Out: ([u"def add(a, b=1):
", u" return a + b
"], 1)

In : import inspect

In : inspect.getsourcelines(add)
Out: ([u"def add(a, b=1):
", u" return a + b
"], 1)

In : inspect.getargspec(add)
Out: ArgSpec(args=["a", "b"], varargs=None, keywords=None, defaults=(1,))

In : inspect.getcallargs(add, 10, 2)
Out: {"a": 10, "b": 2}

In : inspect.isclass(add)
Out: False

In : inspect.isfunction(add)
Out: True

它在實際工作中還能有什麼意義,通過自省獲取方法的參數,從而設置緩存的鍵,如 flask-cache/__init__.py at master · thadeusb/flask-cache · GitHub 和 douban-mc/decorator.py at master · douban/douban-mc · GitHub

5. Mixin模式。它是什麼先看 Mixin是什麼概念? - Python 。假如我們想通過python內置類型Dict的方式來存放數據,編寫的類可以混入DictMixin就好了:

from UserDict import DictMixin
class MyDict(DictMixin):
def __init__(self, dict=None, **kwargs):
self.data = {}
if dict is not None:
self.update(dict)
if len(kwargs):
self.update(kwargs)
def __getitem__(self, id):
return self.data[id]
def __setitem__(self, id, value):
self.data[id] = value
def __delitem__(self, id):
del self.data[id]
def keys(self):
return self.data.keys()

PS: 如果你想兼容Python 2.6以下和Python 3,可以使用collections.MutableMapping:

try:
from UserDict import DictMixin
except ImportError:
from collections import MutableMapping as DictMixin

但是MutableMapping需要額外實現__iter__和__len__。PPS: MutableMapping是學習實現抽象類的範例cpython: 522adc2e082a Lib/_abcoll.py,它繼承了Iterable和Sized,而Iterable中通過abstractmethod要求你必須定義__iter__方法(cpython: 522adc2e082a Lib/_abcoll.py),Sized中要求你必須定義__len__ (cpython: 522adc2e082a Lib/_abcoll.py)否則就會提示:

TypeError: Can"t instantiate abstract class MyDict with abstract methods __iter__, __len__

http://weixin.qq.com/r/D0zH35LE_s_Frda89xkd (二維碼自動識別)


可以看看我的博客,這是我邊看邊思考的記錄,目前還沒寫完,基本上一天一到兩篇的節奏。

Python的高級特性1:容易忽略的不可變類型

Python的高級特性2:列表推導式,生成器與迭代器

python的高級特性3:神奇的__call__與返回函數

Python的高級特性4:函數式編程

Python的高級特性5:談談python的動態屬性

Python的高級特性6:使用__slots__真的能省很多內存

Python的高級特性7:閉包和裝飾器

Python的高級特性8:你真的了解類,對象,實例,方法嗎

Python的高級特性9:蹩腳的多態

Python的高級特性10:無聊的@property

Python的高級特性11:拓展基本數據類型(dict)


個人覺得python語言最為重要的哲學是可讀性,所以提高代碼的可讀性是最為重要的,也是區分於初級技巧的高級技巧。

往往完成一件事是容易的,所不同的是其中的成本,是優雅程度。


推薦看一下《Python高級編程》。

裡面比如yield、property等用法就算是比較高級的技巧了。

細說有很多,一一列舉出來也太費勁。

至於列表解析什麼的算是挺基礎的東西了。


推薦一下 Stack Overflow 上這個帖子:

Hidden features of Python


技巧沒有大用, 關係是思想與概念。 學得越多,技巧忘記得越多, 簡單的深刻的道理則會陪伴你一生。

我自己在python中,如果說技巧,就是教程上說的,list的那些用法, dict, defaultdict, collection, set, array, numpy, blist, event, socket, cython, __init__, __all__, __doc__, keyerror還有些常用的庫。 這些標準教程上的東西,你學會了,給自己幫助很大。 也都是技巧 。

偶爾用一用lambda, map, filter, zip就足夠了。 可以縮小代碼量。

多用multiprocess少用thread和threading。 有時間可以研究一下stackless python, twist,它的思想很受啟發。 tornado, django, jinja2等都需要學一下,簡單實用,強大。

最近流行的openstack也要看一下。zope這東西太古老了,如果你真有時間還是可以借鑒一下。
python2, python3都要學習。 不能一味抵制python3, 其中有很多好的思想。

GIL不是不可逾越的。

如果喜歡windows就學一學win32 api, 反之QT, wxwindows, gtk都可以看一看。 html5, node.js, javascript, bootstrap都是好的GUI工具。 要想快速開發, 很失望的說,只有在windows平台下可以找到可視化的快速開發工具。 C#, delphi, 都是很難超越的東西。

python用得人多, 用好的人也多。 但是水準高,思想又好,編程也強大,可以創造性的做產品的人不多。 相反,模仿別人, 借鑒其它的庫,拿來主義,這是python的特點。 swig這個東西學一學。

以後你還會依賴其它的語言,需要的時候就多學一學其它的語言,甚至 ruby也是必要的。 java, c++, haskell, go, lua, javascript, php, scala.

但是有一天,python一定會衍生出不一樣的版本。越超所有的語言,我相信。 但是不是最近。 這些所有的語言都沒有挑戰性。新的語言會帶來新的設計模式。

我們寫Python代碼的時候經常將一系列操作放在一個語句塊中,Python 2.5加入了with語法,實現上下文管理功能,這讓代碼的可讀性更強並且錯誤更少。最常見的例子就是open,如果不使用with,使用open會是這樣:

如果使用with,可以簡化為兩行:

在執行完縮進的代碼塊後會自動關閉文件。創建上下文管理器實際就是創建一個類,添加__enter__和__exit__方法。看看如何實現open的上下文管理功能:

自定義上下文管理器確實很方便,但是Python標準庫還提供了更易用的上下文管理器工具模塊contextlib,它是通過生成器實現的,我們不必再創建類以及__enter__和__exit__這兩個特殊的方法:

yield關鍵詞把上下文分割成兩部分:yield之前就是__init__中的代碼塊;yield之後其實就是__exit__中的代碼塊;yield生成的值會綁定到with語句as子句中的變數(如果沒有生成,也就沒有as字句)。

2. total_ordering 。對比自定義對象需要添加__lt__、__le__、__gt__、__ge__和__eq__等方法,如果使用total_ordering,只需要定義__eq__以及__lt__、__le__、__gt__、__ge__四種之一就可以了:

3. 有時候BUG隱藏的太深,需要對上下文都有清晰的展示來幫助判斷。用pdb調試不方便,用print不直觀。可以使用如下函數獲取當前調用棧:

4. inspect 。有時候我們想查看一下對象的一些信息或者做類型檢查,也就是自省(檢查某些事物以確定它是什麼、它知道什麼以及它能做什麼):

它在實際工作中還能有什麼意義,通過自省獲取方法的參數,從而設置緩存的鍵,如 flask-cache( https://github.com/thadeusb/flask-cache/blob/master/flask_cache/__init__.py#L418)和 douban-mc(https://github.com/douban/douban-mc/blob/master/douban/mc/decorator.py#L39)

5. Mixin模式 。它是什麼先看「Mixin是什麼概念? 」

寫Python代碼的時候經常將一系列操作放在一個語句塊中,Python 2.5加入了with語法,實現上下文管理功能,這讓代碼的可讀性更強並且錯誤更少。最常見的例子就是open,如果不使用with,使用open會是這樣:

如果使用with,可以簡化為兩行:

在執行完縮進的代碼塊後會自動關閉文件。創建上下文管理器實際就是創建一個類,添加__enter__和__exit__方法。看看如何實現open的上下文管理功能:

自定義上下文管理器確實很方便,但是Python標準庫還提供了更易用的上下文管理器工具模塊contextlib,它是通過生成器實現的,我們不必再創建類以及__enter__和__exit__這兩個特殊的方法:

yield關鍵詞把上下文分割成兩部分:yield之前就是__init__中的代碼塊;yield之後其實就是__exit__中的代碼塊;yield生成的值會綁定到with語句as子句中的變數(如果沒有生成,也就沒有as字句)。

2. total_ordering 。對比自定義對象需要添加__lt__、__le__、__gt__、__ge__和__eq__等方法,如果使用total_ordering,只需要定義__eq__以及__lt__、__le__、__gt__、__ge__四種之一就可以了:

3. 有時候BUG隱藏的太深,需要對上下文都有清晰的展示來幫助判斷。用pdb調試不方便,用print不直觀。可以使用如下函數獲取當前調用棧:

4. inspect 。有時候我們想查看一下對象的一些信息或者做類型檢查,也就是自省(檢查某些事物以確定它是什麼、它知道什麼以及它能做什麼):

它在實際工作中還能有什麼意義,通過自省獲取方法的參數,從而設置緩存的鍵,如 flask-cache( https://github.com/thadeusb/flask-cache/blob/master/flask_cache/__init__.py#L418)和 douban-mc(https://github.com/douban/douban-mc/blob/master/douban/mc/decorator.py#L39)

5. Mixin模式 。它是什麼先看「Mixin是什麼概念? 」

寫Python代碼的時候經常將一系列操作放在一個語句塊中,Python 2.5加入了with語法,實現上下文管理功能,這讓代碼的可讀性更強並且錯誤更少。最常見的例子就是open,如果不使用with,使用open會是這樣:

如果使用with,可以簡化為兩行:

在執行完縮進的代碼塊後會自動關閉文件。創建上下文管理器實際就是創建一個類,添加__enter__和__exit__方法。看看如何實現open的上下文管理功能:

自定義上下文管理器確實很方便,但是Python標準庫還提供了更易用的上下文管理器工具模塊contextlib,它是通過生成器實現的,我們不必再創建類以及__enter__和__exit__這兩個特殊的方法:

yield關鍵詞把上下文分割成兩部分:yield之前就是__init__中的代碼塊;yield之後其實就是__exit__中的代碼塊;yield生成的值會綁定到with語句as子句中的變數(如果沒有生成,也就沒有as字句)。

2. total_ordering 。對比自定義對象需要添加__lt__、__le__、__gt__、__ge__和__eq__等方法,如果使用total_ordering,只需要定義__eq__以及__lt__、__le__、__gt__、__ge__四種之一就可以了:

3. 有時候BUG隱藏的太深,需要對上下文都有清晰的展示來幫助判斷。用pdb調試不方便,用print不直觀。可以使用如下函數獲取當前調用棧:

4. inspect 。有時候我們想查看一下對象的一些信息或者做類型檢查,也就是自省(檢查某些事物以確定它是什麼、它知道什麼以及它能做什麼):

它在實際工作中還能有什麼意義,通過自省獲取方法的參數,從而設置緩存的鍵,如 flask-cache( https://github.com/thadeusb/flask-cache/blob/master/flask_cache/__init__.py#L418)和 douban-mc(https://github.com/douban/douban-mc/blob/master/douban/mc/decorator.py#L39)

5. Mixin模式 。它是什麼先看「Mixin是什麼概念? 」

其實python非常適合初學者入門。相比較其他不少主流編程語言,有更好的可讀性,因此上手相對容易。自帶的各種模塊加上豐富的第三方模塊,免去了很多「重複造輪子」的工作,可以更快地寫出東西。配置開發環境也不是很複雜,mac和linux都內置了python。另外據我所知,不少學校也開始使用python來教授程序設計課程(比如本人的母校)。

我就是完全通過網上資源自學python的。

從在校時候用python接活賺零花錢,到在創業公司用python開發商業網站和遊戲後台。所有遇到的問題,幾乎都可以從互聯網上的公開資源找到答案。

關於自學python,個人最大的3點經驗:

找一本淺顯易懂,常式比較好的教程,從頭到尾看下去。不要看很多本,專註於一本。把裡面的常式都手打一遍,搞懂為什麼。我當時看的是《簡明python教程》,不過這本書不是非常適合零基礎初學者。

去找一個實際項目練手。我當時是因為要做一個網站,不得已要學python。這種條件下的效果比你平時學一門新語言要好很多。所以最好是要有真實的項目做。可以找幾個同學一起做個網站之類。注意,真實項目不一定非要是商業項目,你寫一個只是自己會用的博客網站也是真實項目,關鍵是要核心功能完整。

最好能找到一個已經會python的人。問他一點學習規劃的建議(上知乎也是個途徑),然後在遇到卡殼的地方找他指點。這樣會事半功倍。但是,要學會搜索,學會如何更好地提問。沒人願意幫你寫作業或是回答「一搜便知」的問題。

然而,別人的經驗未必能完全複製。比如我沒有說的是,在自學python之前,我已在學校系統學習過其他的編程語言。

對於完全沒有編程經驗的初學者,在學習python的時候,面對的不僅僅是python這門語言,還需要面臨「編程」的一些普遍問題,比如:

從零開始,不知道從何入手,找了本編程教材發現第二章開始就看不懂了

缺少計算機基礎知識,被一些教程略過的「常識性」問題卡住

遇到問題不知道怎麼尋找解決方案

看懂語法之後不知道拿來做什麼,學完一陣子就又忘了

缺少數據結構、設計模式等編程基礎知識,只能寫出小的程序片段

所以除了前面說的3點經驗,給初學編程者的額外建議:

首先要有信心。雖然可能你看了幾個小時也沒在屏幕上打出一個三角形,或者壓根兒就沒能把程序運行起來。但相信我,幾乎所有程序員一開始都是這麼折騰過來的。

選擇合適的教程。有些書很經典,但未必適合你,可能你寫了上萬行代碼之後再看它會比較好。

寫代碼,然後寫更多的代碼。光看教程,編不出程序。從書上的常式開始寫,再寫小程序片段,然後寫完整的項目。

除了學習編程語言,也兼顧補一點計算機基礎,和英語。

不但要學寫代碼,還要學會看代碼,更要會調試代碼。讀懂你自己程序的報錯信息。再去找些github上的程序,讀懂別人的代碼。

學會查官方文檔,用好搜索引擎和開發者社區

自己多問下為什麼學python

如果一門語言沒有改變你的編程思維,那麼它不值得你去學習」。如果這麼說,我們大學的時候,學習了c,c++,java,C#,算是值得學習么?很多時候是不值得,我覺得我們大學的課程就是用java,c#,c++把"C程序設計"又上了一遍.

這是因為,學校的老師會C和java之類的,所以要跟著規矩開這門課,(這也就是為什麼,許多學校還在教vb,),這也就是為什麼,你所以為的一樣就是大家都有For都有while,都有switch..都有Class...都有int 都有float,所謂的不一樣就是用C有指針,java沒有,這就是為什麼教育是失敗的,這也就是為什麼,我目前認識的幾個編程大牛

python的優點:簡單 我所說的簡單,是相比於象C和C++這樣的語言,你為了編程,要學習許多偏底層的東西.在比如,你在學習一個新的編程範式,或者想要馬上做個例子看看,試驗某個API,如果你是寫java的,你不得不去寫一個main,寫一些構造,即使有IDE這樣的東西,能夠為你帶來代碼生成器,而我做得就是寫一段「腳本」,或者打開python互動式解釋器就行了。

自己認識的python朋友出去工作,工資比較高,然後自己又剛剛好是會python所以選擇學習python,這樣的人比較危險但是也比較有激勵,還有就是覺得python比其他開發語言好用。

學完python前景會咋樣

其實我個人是很看好python未來的就業前景的,因為我認識太多的工程師都已經在學python,很多都是月收入大幾萬的

我個人也並非一直用python。前些年主要用c/c++以及java開發一些通信,移動系統,互聯網通信。近3年開始才轉向python。坦白的說,這可能與你相處的公司以及環境不大一樣。隨便舉個例子,google的protocol buffer協議一出來就具有c++/python/java三種語言支持。google的廣告系統早在03,04年左右就一併對python進行了webservice支持,大部分涉及基礎核心系統的公司,都開始對python進行了擴展支持。甚至開源社區的postgresql資料庫,除了自身的ansi SQL,pgsql,pg/TCL,PG/PERL之外對python進行了內嵌支持,唯獨卻沒有呼聲很高的java。在FREEBSD(MIT)/LINUX(GPL)平台上,對java可能排斥性比較大,但綜合而言,目前python發展還沒有java那種普及,主要是python大部分工作仍然是在較為深入地系統層和框架層做設計開發,例如django,SQLAlchemy,fail2ban,mail郵件系統,twisted等等。這部分對於那種習慣應用前輩們框架的編碼人員而言,缺乏創造力的他們根本無法適用這種開發。尤其在python涉及一些系統層面需要有較強的c/c++能力,這部分人在國內要麼就累得要死沒時間,要麼就啥都不會就會拷貝代碼,而國內公司也鮮有主動去做這部分基礎勞動的,大多都是等別人做好了在直接拿來用,所以造就了任何技術性的東西出來,國內都是先等等看,然後抄襲應用。

大環境如此,但千萬誤認為先等等看吧。對於一個技術人員而言,缺乏對新技術的渴望與熱情,這是一種非常危險的事情。我工作8年了,按照國內很多的人的說法早已不做代碼了,但又一次在聽一個老外的演講,他說他50多歲仍然每天堅持寫代碼,了解最新的動態,所以他才能做到他們公司的首席科學家,因此它才能時刻指導項目團隊前進並保證項目的質量。他坦言對於一個不寫代碼並且不了解最新的技術動態的技術人員或者技術團隊的負責人而言,這種團隊也就足夠做作小項目,一旦壓力和項目過大,就會有很多問題漏出來。

對於新人而言,無論學習什麼技術,都要以鼓勵的姿態出現。太多用薪水和你個人所看到的現狀去衡量一門技術,那絕對是欠缺眼光的。任何一門技術,一旦有人學習,他有可能逐漸成為這個領域的專家,即便再濫再沒有人用的開發語言技術,他也有可能就是明日的奠基者或者大師。

最後:自己如何確定目標

在生活中學會不斷挖掘自己的潛力。我們都是一個普通人,可能並不清楚自己到底在哪方面佔有優勢。所以,學著在生活中找到自己的優勢,並根據優勢選擇一定的就業方向。

不隨波逐流。不要看周圍的人做什麼,自己就做什麼,也許別人做的並不適合你。別人的優勢很可能會成為你的劣勢。所以,堅定自己的想法,讓自己知道那些方面適合自己,自己可以勝任。

不斷嘗試可能成為自己的優勢。你不知道什麼適合自己,所以才要大膽、勇敢地嘗試。找到一種可以屬於你的獨特的優勢。

堅定信念。一旦你堅定了自己的信念,就不要被別人的意見或是諷刺或是嘲笑所干擾。別人不是你,不懂的你在想什麼,不清楚你開始這件事的源頭。你的事情,不了解你的人,沒有資格輕易評說。

不茫然,不多想。別讓太多的事干擾到你奮鬥下去的信念。夢想不容許太多的雜念。那些雜念只會讓你的心愈來愈脆弱,多為一個人考慮,到頭來,傷害的還是自己。

選擇自己學習方法

每個人都有適合自己的方法,有的人去選擇自學,有的人選擇看視頻學習,有的人選擇報名培訓班,那在這個時候,你就要自己考慮清楚,到底那樣對的幫助是最大的,個人覺得是跟著培訓班最好的,畢竟人家的實戰項目多,我們學軟體開發的都知道實戰項目對於學好一門語言是 很重要的。

學習python有那些誤區

具體裡面的誤區非常的多,那些就不需要我去寫出來,我給你說的一般都是心態的問題,首先一個覺得自己會java和c++,然後我學習python就很牛,但是你要知道語言是有很多相同的地方,但是不是通用,一定要自己學習的仔細。還有一種就是覺得我不會英語,我要先去把英語學習好在來學python。因為自己想還壞主意然後學習,這樣的都是容易找進誤區的。

怎麼樣才能學好python

學好python你需要一個良好的環境,一個優質的開發交流群,群里都是那種相互幫助的人才是可以的,我有建立一個python學習交流群,在群里我們相互幫助,相互關心,相互分享內容,這樣出問題幫助你的人就比較多,群號是304050799,這樣就可以找到大神聚合的群,如果你只願意別人幫助你,不願意分享或者幫助別人,那就請不要加了,你把你會的告訴別人這是一種分享。


沒用過什麼高級技巧,只說一些團隊協作中的小技巧吧:

1. docstring

給模塊或類、函數寫docstring是個好習慣,看看官方示例:

&>&>&> def my_function():
... """Do nothing, but document it.
...
... No, really, it doesn"t do anything.
... """
... pass
...
&>&>&> print my_function.__doc__
Do nothing, but document it.

No, really, it doesn"t do anything.

不管是給自己看還是給別人看都非常方便。

2. sha-bang

考慮到可移植性,我們一般會這樣寫:

#!/usr/bin/env python

這樣系統會在環境變數中尋找Python,而不是某個可能不是很可靠的固定位置。

3. 編碼

簡單,sha-bang之後加上:

# -*- coding: encoding -*-

項目中經常會用到中文,所以通常是:

# -*- coding: UTF-8 -*-

4. 導入模塊

可以直接import模塊,但是用起來比較麻煩,像這樣:

import module
module.name()

這種寫法用起來更簡單:

from module import name
name()

如果name與當前模塊中的名字有衝突怎麼辦?

from module import name as myname
myname()

5. 調試

使用內部變數__name__,當模塊是單獨執行的時候,__name__的值為__main__,當模塊是被導入執行的時候,__name__的值為被導入模塊的名字,所以一般在調試py文件的時候,會這樣寫:

if __name__ == "__main__":
foo()

這樣做完單文件調試,在模塊被導入的時候,又不會執行調試代碼。

暫時就想到這麼多。


Lambda

比如

calculator{
"plus" : lambda x,y : x + y,
"minus" : lambda x,y : x - y
}

res = calculator["plus"](2, 3) # res = 5

zip 置換矩陣

比如

matrix = [[1, 2, 3],[4, 5, 6]]
res = zip( *matrix ) # res = [(1, 4), (2, 5), (3, 6)]


把函數當成類用

版本一:保存內部狀態的

# -*- coding: utf-8 -*-
"""
Created on Sun Dec 31 12:21:33 2017

@author: zbg
"""

def Point(xx, yy):
def point():
point.x, point.y = xx, yy#這樣設計是為了保證每個實例這裡只執行一次
def functions(f):
def reset():
point.x = point.y = 0
def addn(n):
point.x += n
point.y += n
def addxy(xx, yy):
point.x += xx
point.y += yy
def getx():
return point.x
def gety():
return point.y
def addP(P):
point.x += P("getx")()
point.y += P("gety")()
def show():
print point.x, point.y

return eval(f)
return functions
return point()

p1 = Point(123,456)
p2 = Point(321,222)
p1("show")()
p2("show")()
p1 ("addP") (p2)
p1("show")()
p1("addn") (-2)
p1("show")()
p1 ("reset")()
p1("show")()

版本二:純函數的

# -*- coding: utf-8 -*-
"""
Created on Sun Dec 31 09:41:16 2017

@author: zbg
"""
def Point(x, y):
def functions(f):
def reset():
return Point(0, 0)
def addn(n):
return Point(x + n, y + n)
def addxy(xx, yy):
return Point(x + xx, y + yy)
def getx():
return x
def gety():
return y
def addP(P):
return Point(x + P("getx")(), y + P("gety")())
def show():
print x, y
return Point(x, y)

return eval(f)
return functions

p1 = Point(123,456)
p2 = Point(321,222)
p1("show")()
p2("show")()
p1 = p1 ("addP") (p2)("show")()("addn") (-2)("show")()("reset")()
p1("show")()

輸出結果:

123 456
321 222
444 678
442 676
0 0


如何更牛逼的使用api


多用import


無論你寫的有多高級,別人看不懂都白搭。所以我的"高級"技巧是寫注釋,恰到好處的注釋。


一言不和貼代碼:

用python的__new__方法實現單例模式(這種方法還是不夠完美,因為__init__如果有參數需要初始化需要單獨處理)

代碼片段1

# coding=utf-8
class ClassName(object):

"""docstring for ClassName"""
def __new__(cls, *args, **kwargs):
# cls為類對象ClassName,去類對象裡面查看是否有instances這個實例
if not hasattr(cls, "instances"):
# instances就是__new__方法生成的ClassName的實例對象
instances = super(ClassName, cls).__new__(cls, *args, **kwargs)
# 將實例對象instances存在類對象裡面
cls.instances = instances
return cls.instances

def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg

a = ClassName(3)
b = ClassName(2)
print id(a)
print id(b)

代碼片段2

# coding=utf-8
import functools

class Singleton(object):
# 定義一個類變數字典,用於存儲所有的單例
obj_dict = {}

def __new__(cls, *args, **kwargs):
if not hasattr(cls, "instances"):
instances = super(Singleton, cls).__new__(cls, *args, **kwargs)
cls.instances = instances
return cls.instances

def __init__(self, *l_args, **l_kwargs):
pass

def __call__(self, cls):
@functools.wraps(cls)
def wrapper(*args, **kwargs):
# 這是一個閉包,閉包外的代碼只會跑一次喲
if not self.obj_dict.has_key(cls):
ret = cls(*args, **kwargs)
self.obj_dict[cls] = ret
return self.obj_dict[cls]
return wrapper

@Singleton()
class ClassName(object):

def __init__(self, a):
pass

@Singleton()
class ClassName123(object):

def __init__(self, a):
pass

a = ClassName(23)
b = ClassName(43)
print id(a)
print id(b)

a = ClassName123(23)
b = ClassName123(43)
print id(a)
print id(b)

代碼片段3

# coding=utf-8
import functools

def Singleton(*args, **kwargs):
def wrapper_first(cls):
@functools.wraps(cls)
def wrapper(*l_args, **l_kwargs):
if not hasattr(cls, "instances"):
ret = cls(*l_args, **l_kwargs)
cls.instances = ret
return cls.instances
return wrapper
return wrapper_first

@Singleton()
class ClassName(object):

def __init__(self, a):
pass

@Singleton()
class ClassName123(object):

def __init__(self, a):
pass

a = ClassName(23)
b = ClassName(43)
print id(a)
print id(b)

a = ClassName123(23)
b = ClassName123(43)
print id(a)
print id(b)

更多請見。

Python設計模式匯總,分析,實戰coding

持續更新中


zip 可以看成是交換一個多維數組的前兩個維度。


http://book.pythontips.com/en/latest/


我也就不列舉一些比較基礎的了,想想還是匿了吧,免得被一些Python廚噴

迭代器什麼的

這裡倒有一個Python的元編程的技巧。不知道用的人多不多?

Python實現ruby的method missing

#coding=utf-8

class Test(): def __getattr__(self, item):

def method_missing(*args):
print("calling method missing")
print("using args {0}".format(args))
print(f"functionn name : {item}")
return [i+1 for i in args]
return method_missing
a = Test()
print(a.test(1,2,3,4,5))
print("
")
print(a.test2(7862354,2345,3426,3475126))

總之感覺元編程本身就很酷。

好像還有一些,剛看下面某位「大神」的答案很不爽,只知道裝逼算什麼大神?什麼叫「說了你也不懂」 eval你以為新人就不懂?字裡行間看出就會一個普通的eval有啥可驕傲的。說的像自己是神一樣的。

不過他也提到了eval

可以在Python內執行Python代碼,方便,有風險

比如說在移除列表裡的0的時候,解釋器會把false也給移走了。這時候eval的作用就出來了(我用的不多)

Python的magic methods算是比較強大了

對了,好像有一個dis庫?可以列出運行步驟

import dis

dis.dis()

當然算不上什麼奇淫技巧


可以看看Python高級編程

還有 http://www.kokojia.com/course-526.html 這個鏈接里的東東挺不錯的,有興趣的看看,希望可以幫到你


寫python肯定用協程了


推薦閱讀:

excel中想實現使用Python代替VBA,請問應該怎麼做?
如何優雅的安裝Python的pandas?
怎樣使 Python 輸出時不換行?
Python 的縮進有多重要?

TAG:Python |