Python Study Note(1)

變量

  • 除法
>>> 9 / 3
3.0
>>> 10 // 3
3
  • 字符串多個(gè)空行
print('''line1
line2
line3''')

list,tuple

  • list:可變數(shù)組classmates = ['Michael', 'Bob', 'Tracy']
classmates[-1] #末尾元素
classmates.pop() #刪除末尾元素
classmates.pop(1) #刪除索引1元素
classmates[1] = "Chen"  ##替代元素
classmates.insert(1,'Jack')
classmates.append('Bai')
  • tuple:不可變數(shù)組classmates = ('Michael', 'Bob', 'Tracy')
    t = (1,) #只有一個(gè)元素時(shí)須加,

條件判斷

age = 3
if age >= 18:
    print('your age is', age)
    print('adult')
else:
    print('your age is', age)
    print('teenager')

":"代表后面縮進(jìn)的部分都是他的塊。

循環(huán)

  • for x in ...: 遍歷
sum = 0
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
    sum = sum + x
print(sum)
  • random()函數(shù):
>>> range(5)
[0, 1, 2, 3, 4]
  • while
sum = 0
n = 99
while n > 0:
    sum = sum + n
    n = n - 2
print(sum)
  • break:在循環(huán)過程中直接退出循環(huán)
  • continue:提前結(jié)束本輪循環(huán),并直接開始下一循環(huán)

字典

判斷key是否存在
  • in
>>> 'Thomas' in d
False
  • get
>>> d.get('Thomas') #返回None的時(shí)候,交互式命令行不顯示結(jié)果
>>> d.get('Thomas', -1) #如果key不存在,返回None或者指定的value
-1
基本操作
  • 刪除key >>> d.pop('Bob')
set:也是一組key的集合,但不存儲(chǔ)value。由于key不能重復(fù),所以,在set中,沒有重復(fù)的key
>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}

函數(shù)

if not isinstance(x, (int, float)):
        raise TypeError('bad operand type')

函數(shù)參數(shù)

  • 位置參數(shù) def power(x):
  • 默認(rèn)參數(shù) def power(x, n=2): # power(5)相當(dāng)于power(5,2)

注意: 默認(rèn)參數(shù)必須指向不變對(duì)象

  • 可變參數(shù):可變參數(shù)允許你傳入0個(gè)或任意個(gè)參數(shù),這些可變參數(shù)在函數(shù)調(diào)用時(shí)自動(dòng)組裝為一個(gè)tuple。
def calc(*numbers): #在函數(shù)內(nèi)部,參數(shù)numbers接收到的是一個(gè)tuple
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
calc(1, 2)

如果已經(jīng)有一個(gè)list或者tuple

>>> nums = [1, 2, 3]
>>> calc(*nums)
  • 關(guān)鍵字參數(shù):關(guān)鍵字參數(shù)允許你傳入0個(gè)或任意個(gè)含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict。
def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

如果已經(jīng)有一個(gè)dict

>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
  • 命名關(guān)鍵字參數(shù):如果要限制關(guān)鍵字參數(shù)的名字,就可以用命名關(guān)鍵字參數(shù)。
def person(name, age, *, city, job): #只接受city,job作為關(guān)鍵字參數(shù)
    print(name, age, city, job)

如果函數(shù)定義中已經(jīng)有了一個(gè)可變參數(shù),后面跟著的命名關(guān)鍵字參數(shù)就不再需要一個(gè)特殊分隔符*了:

def person(name, age, *args, city, job):
    print(name, age, args, city, job)
  • 參數(shù)組合:參數(shù)定義的順序必須是:必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)。

使用args和*kw是Python的習(xí)慣寫法,當(dāng)然也可以用其他參數(shù)名,但最好使用習(xí)慣用法。

切片

L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']

>>> L[:3]
['Michael', 'Sarah', 'Tracy']
>>> L[1:3]
['Sarah', 'Tracy']

>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']

tuple和字符串也可以使用。

>>> L[:10:2]  前10個(gè)數(shù),每兩個(gè)取一個(gè):
[0, 2, 4, 6, 8]

高級(jí)特性

迭代

dict迭代:默認(rèn)情況下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同時(shí)迭代key和value,可以用for k, v in d.items()。

其他語言中是通過下標(biāo)完成,如下

for (i=0; i<list.length; i++) {
    n = list[i];
}

如果我們希望在python中使用,Python內(nèi)置的enumerate函數(shù)可以把一個(gè)list變成索引-元素對(duì),這樣就可以在for循環(huán)中同時(shí)迭代索引和元素本身:

>>> for i, value in enumerate(['A', 'B', 'C']):
...     print(i, value)
...
0 A
1 B
2 C

以上形式,在python中較為常用。

>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
...     print(x, y)
...
1 1
2 4
3 9
列表生成式
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
生成器

將列表生成器變?yōu)樯善?/p>

>>> L = [x * x for x in range(10)]
>>> g = (x * x for x in range(10))

>>> next(g)  #一個(gè)一個(gè)打印
>>> g = (x * x for x in range(10))   #循環(huán)打印
>>> for n in g:
...     print(n)
... 

將函數(shù)變?yōu)樯善鳎?/p>

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b               #加入yield
        a, b = b, a + b
        n = n + 1
    return 'done'

>>> for n in fib(6):
...     print(n)
...
1
1
2
3
5
8

例子

def triangles():
    n, L = 1, []
    while True:
        n, L = n+1, [1 if(i == len(L) or i == 0) else  L[i - 1] + L[i] for i in range(len(L)+1)]
        yield L
n = 0

for t in triangles():
    print(t)
    n = n + 1
    if n == 10:
        break

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
迭代器
  • 可迭代對(duì)象Iterable:可以直接作用于for循環(huán)的對(duì)象統(tǒng)稱為可迭代對(duì)象。一類是集合數(shù)據(jù)類型,如list、tuple、dict、set、str等;一類是generator,包括生成器和帶yield的generator function。

可以使用isinstance()判斷一個(gè)對(duì)象是否是Iterable對(duì)象:

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
  • 迭代器Iterator:可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象稱為迭代器,表示的是一個(gè)數(shù)據(jù)流。

可以使用isinstance()判斷一個(gè)對(duì)象是否是Iterator對(duì)象:

>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
  • 把list、dict、str等Iterable變成Iterator可以使用iter()函數(shù):
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

函數(shù)式編程

  • map:map()函數(shù)接收兩個(gè)參數(shù),一個(gè)是函數(shù),一個(gè)是Iterable,map將傳入的函數(shù)依次作用到序列的每個(gè)元素,并把結(jié)果作為新的Iterator返回。
>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)            #list()函數(shù)讓它把整個(gè)序列都計(jì)算出來并返回一個(gè)list。
[1, 4, 9, 16, 25, 36, 49, 64, 81]
  • reduce:reduce把一個(gè)函數(shù)作用在一個(gè)序列[x1, x2, x3, ...]上,這個(gè)函數(shù)必須接收兩個(gè)參數(shù),reduce把結(jié)果繼續(xù)和序列的下一個(gè)元素做累積計(jì)算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

將str變?yōu)閕nt并計(jì)算

>>> from functools import reduce
>>> def fn(x, y):
...     return x * 10 + y

...
>>> def char2num(s):
...     return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579

  • filter:主要用于過濾,把傳入的函數(shù)依次作用于每個(gè)元素,然后根據(jù)返回值是True還是False決定保留還是丟棄該元素。
def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 結(jié)果: [1, 5, 9, 15]
  • sort:除普通排序外,它還可以接收一個(gè)key函數(shù)來實(shí)現(xiàn)自定義的排序,例如按絕對(duì)值大小排序。
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] 
def by_name(t): 
    return t[0] 
L2=sorted(L,key=by_name) 

key=str.lower 忽略大小寫 reverse=True 反向排序

匿名函數(shù)
lambda x: x * x 

**等價(jià)于下列內(nèi)容**
def f(x):
    return x * x
裝飾器
def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

@log  #把@log放到now()函數(shù)的定義處,相當(dāng)于執(zhí)行了語句:now = log(now)

def now(): 
    print('2015-3')

now()

$ python a.py
call now():
2015-3

帶參數(shù)的decorator

import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')   #相當(dāng)于>>> now = log('execute')(now)
偏函數(shù)
ef int2(x, base=2):
    return int(x, base)

##把一個(gè)函數(shù)的某些參數(shù)給固定住(也就是設(shè)置默認(rèn)值),返回一個(gè)新的函數(shù),調(diào)用這個(gè)新函數(shù)會(huì)更簡單。

>>> import functools
>>> int2 = functools.partial(int, base=2)
內(nèi)置函數(shù)

https://docs.python.org/3/library/functions.html

模塊

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

' a test module '    #文檔注釋

__author__ = 'Michael Liao'    

import sys

def test():
    args = sys.argv
    if len(args)==1:
        print('Hello, world!')
    elif len(args)==2:
        print('Hello, %s!' % args[1])
    else:
        print('Too many arguments!')

if __name__=='__main__':    #當(dāng)我們?cè)诿钚羞\(yùn)行hello模塊文件時(shí),Python解釋器把一個(gè)特殊變量__name__置為__main__,而如果在其他地方導(dǎo)入該hello模塊時(shí),if判斷將失敗,因此,這種if測(cè)試可以讓一個(gè)模塊通過命令行運(yùn)行時(shí)執(zhí)行一些額外的代碼,最常見的就是運(yùn)行測(cè)試。
    test()


使用域
  • 公開的,可以被直接引用:比如:abc,x123,PI等;
  • 特殊的:類似xxx這樣的變量是特殊變量,可以被直接引用,但是有特殊用途,比如上面的authorname就是特殊變量。
  • 非公開的:類似_xxx和__xxx這樣的函數(shù)或變量就是非公開的(private),不應(yīng)該被直接引用,比如_abc,__abc等。

面向?qū)ο缶幊?/h3>

訪問限制
class Student(object):
    """docstring for Student."""
    def __init__(self, name, score):
        self.__name = name      #__name私有變量
        self.__score = score

    def set_score(self, score):   #從外部修改私有變量,
        self._score = score
    def set_name(self, name):
        self._name =name

    def get_score(self):    #從外部訪問獲取私有變量
        return self.__score
    def get_name(self):
        return self.__name

    def print_score(self):
        print('%s:%s' % (self._name,self._score))

Bai = Student('Bai', 100)

BaiName = Bai.get_name() 
獲取對(duì)象信息
  • type
>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
>>> type('abc')==str
True
>>> type(123)==int
True
  • isinstance:相比較type,更能反映繼承關(guān)系,同時(shí)可以判斷是否是某些類型中的一種
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
  • dir:獲得一個(gè)對(duì)象的所有屬性和方法。
>>> dir('ABC')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

類似xxx的屬性和方法在Python中都是有特殊用途的,下列就是等價(jià)的

>>> len('ABC')
3
>>> 'ABC'.__len__()
3

配合getattr()、setattr()以及hasattr(),我們可以直接操作一個(gè)對(duì)象的狀態(tài)。

>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...

>>> obj = MyObject()

>>> hasattr(obj, 'x') # 有屬性'x'嗎?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
False
>>> setattr(obj, 'y', 19) # 設(shè)置一個(gè)屬性'y'
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
True
>>> getattr(obj, 'y') # 獲取屬性'y'
19
>>> obj.y # 獲取屬性'y'
19
##也可以獲取方法
>>> getattr(obj, 'power') # 獲取屬性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
  • slots:想要限制實(shí)例的屬性.對(duì)繼承的無效。
class Student(object):
    __slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱

>>> s = Student() # 創(chuàng)建新的實(shí)例
>>> s.name = 'Michael' # 綁定屬性'name'
>>> s.age = 25 # 綁定屬性'age'
>>> s.score = 99 # 綁定屬性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

-@property:綁定屬性時(shí),如果我們直接把屬性暴露出去,雖然寫起來很簡單,但是,沒辦法檢查參數(shù),導(dǎo)致可以把成績隨便改。Python內(nèi)置的@property裝飾器就是負(fù)責(zé)把一個(gè)方法變成屬性調(diào)用。

class Student(object):

    def get_score(self):
         return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

上述寫法過于復(fù)雜,所以需要簡化

class Student(object):
#可讀可寫
    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value
#只可寫
    @property
    def age(self):
        return 2015 - self._birth

  • strrepr:用于優(yōu)化打印結(jié)果
class Student(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return 'Student object (name=%s)' % self.name
    __repr__ = __str__

# __str__部分
>>> print(Student('Michael'))    
Student object (name: Michael)

# __repr__部分
>>> s = Student('Michael')
>>> s
<__main__.Student object at 0x109afb310>
  • getattr:如果一個(gè)類沒有相應(yīng)屬性,那么還可以寫一個(gè)getattr()方法,動(dòng)態(tài)返回一個(gè)屬性。一般默認(rèn)返回None.(只有在沒有找到屬性的情況下,才調(diào)用getattr)
class Student(object):

    def __init__(self):
        self.name = 'Michael'

    def __getattr__(self, attr):
        if attr=='score':
            return 99

  • 枚舉
from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)     #value默認(rèn)從1開始

如果需要更精確地控制枚舉類型,可以從Enum派生出自定義類:

from enum import Enum, unique

@unique                              # @unique裝飾器可以幫助我們檢查保證沒有重復(fù)值。
class Weekday(Enum):
    Sun = 0 # Sun的value被設(shè)定為0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6

元類
  • type:函數(shù)既可以返回一個(gè)對(duì)象的類型,又可以創(chuàng)建出新的類型。我們說class的定義是運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建的,而創(chuàng)建class的方法就是使用type()函數(shù)。
>>> def fn(self, name='world'): # 先定義函數(shù)
...     print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 創(chuàng)建Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class '__main__.Hello'>

要?jiǎng)?chuàng)建一個(gè)class對(duì)象,type()函數(shù)依次傳入3個(gè)參數(shù):

  1. class的名稱;
  2. 繼承的父類集合,注意Python支持多重繼承,如果只有一個(gè)父類,別忘了tuple的單元素寫法;

本筆記參考 Linux探索之旅

  1. class的方法名稱與函數(shù)綁定,這里我們把函數(shù)fn綁定到方法名hello上。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。