看例子,學 Python(一)
看例子,學 Python(二)python
建立一個目錄 myutil
,把 mymath.py
挪到裏面,再添加一個空文件 __init__.py
:segmentfault
myutil/ __init__.py mymath.py
myutil
即是一個包(package)。ide
最直接的用法:函數
>>> import myutil.mymath >>> myutil.mymath.fac(4) 24
缺點是調用 fac
時太長,包和模塊做爲前綴都要寫全。可是寫成 import myutil.mymath.fac
也是不對的。
經過 import
的語法(syntax):優化
import <包>.<包>.<包|模塊>
能夠看出:code
最後一項(item)能夠是包也能夠是模塊,前面的必須是包;對象
最後一項不能夠是類、函數或變量的定義。ip
根據語法來看,能夠 import 一個包:內存
>>> import myutil >>> help(myutil) ...
可是這樣並無什麼實際用處,由於沒法就此調用具體的函數(類、變量):ci
>>> myutil.mymath.fac(4) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: module 'myutil' has no attribute 'mymath'
若是要避免調用時帶着一串前綴,能夠用 from...import
:
>>> from myutil.mymath import fac >>> fac(4) # 再也不須要前綴 24
一次 import 多個時以逗號分割:
>>> from myutil.mymath import fib, fac
一次 import 全部:
>>> from myutil.mymath import *
from...import...
避免了前綴,可是也污染了名字,使用時需權衡。
高階函數(higher-order)就是操做或返回其它函數的函數。
下面是幾個經典的高階函數,其它稍微函數式一點的語言裏通常也有。
用 reduce
重寫階乘:
import operator, functools def fac(n): return functools.reduce(operator.mul, range(1, n+1))
用 reduce
求和:
def sum(n): return functools.reduce(operator.add, range(1, n+1))
Python 的 reduce
就至關於 C++ 的 accumulate
(C++17 已經新增 reduce
)。
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int sum = std::accumulate(v.begin(), v.end(), 0); // 求和 int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); // 求積
>>> list(map(bool, [None, 0, "", u"", list(), tuple(), dict(), set(), frozenset()])) [False, False, False, False, False, False, False, False, False]
None、0、空字符串、以及沒有元素的容器對象均可視爲 False
,反之爲 True
。
>>> list(filter(bool, [None, 0, "", 1])) [1]
==
判斷值是否相等,is
判斷兩個變量是否爲同一個對象。
這就好像 Java 裏的 ==
和 equals
同樣。
下面是一些例子:
>>> a, b = 1, 1 >>> a == b True >>> a is b True
a == b
比較好理解,a is b
是由於 Python 對整數作了優化,a
和 b
都指向同一個預先分配的對象(其值爲 1)。
能夠理解爲 is
比較的是對象的內存地址。
內建函數 id()
返回對象的惟一標識,能夠理解爲內存地址。
>>> id(a), id(b) (35169392, 35169392)
甚至能夠拿到一個對象的引用計數(reference count):
>>> import sys >>> sys.getrefcount(a) 99 >>> sys.getrefcount(b) 99
引用計數爲 99 有點意外,實際上是由於不少裝載的內建模塊都用到了整數 1。
不妨看看其它整數如何:
>>> sys.getrefcount(0) 169 >>> sys.getrefcount(255) 4
對 Python 來講,變量只是名字,它的類型和值取決於它所綁定的對象。咱們能夠把 a
b
綁定到其它對象:
>>> a, b = "hello", "hello" >>> a is b True
一樣,a is b
是由於 Python 對字符串作了優化。
值得一提的是,這種優化(也即引用計數)可能只針對 CPython,對於 Python 的其它實現可能就不是這樣了。你的程序不應依賴於這些特定於解釋器的實現。
整數和字符串有一個共同點,即它們都是不可變的(immutable),如今來看看可變對象,好比列表:
>>> c, d = [a, b], [a, b] >>> c == d True >>> c is d False
可見雖然 c
和 d
具備相等的值,但對象是不一樣的兩個。
這些就是 Python 的數據模型(Data Model),雖然不是所有。
Python 的每個對象(object)都有如下三個部分:
身份(identity)
類型(type)
值(value)
身份:
不可改變(unchangeable)(一旦對象建立了就不會改變)
對應於內存地址
經過操做符 is
進行比較: a is b
函數 id()
返回對象惟一的整形標識(內存地址)
類型:
不可改變(unchangeable)
函數 type()
返回對象類型
值:
可變的(mutable):字典,列表
不可變的(immutable):數字,字符串,元組
最後,對象不會被顯式地銷燬(explicitly destroyed)。
對 CPython 來講,對象由引用計數管理,計數爲 0 時對象會自動銷燬。
最後留一道練習。
給定:
>>> c = [] >>> d = [] >>> c is d False
請問:
>>> e = f = [] >>> e is f ???