Hom's Blog


Python中级篇

列表生成式(映射list)

[expression for i in Iterable], 也可以嵌套: [expression for i in Iterable1 for j in Iterable2], 甚至可以加入判断条件 [expression for i in Iterable if condition]. 循环也可以像一般for循环支持多循环变量. 迭代产生列表时若某项出错,则会报错生成失败.

列表生成器使用一句的语法用生成器生成列表的各个项, 仅适用于列表,而且记得加[..]

就是将迭代的i进行相应表达式操作, 生成相应一个新的列表, 若加入判断条件,列表长度可能改变. 例如

[ x*x for x in range(1,11)]
#->[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[ 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']
d = {'x': 'A', 'y': 'B', 'z': 'C' }
[k + '=' + v for k, v in d.iteritems()]
#->['y=B', 'x=A', 'z=C']
L = ['Hello', 'World', 'IBM', 'Apple']
[s.lower() for s in L]
#->['hello', 'world', 'ibm', 'apple']
g=( x*x for x in range(1,11) );g
#-><generator object <genexpr> at 0x104feab40>
A=[]
for i in g:A.append(i);

将中括号变成小括号, 返回的将是生成器而不是列表.

sorted排序函数

sorted(list[,func]): 对列表排序, 默认从小到大. 可以自定义提供函数func(x,y)来自定义排序, 默认当x < y 返回-1 (即不变顺序), x > y返回1 (即变顺序), x==y 返回0 (即不变顺序).

# 缺省从小到大,所以默认函数
def funcsort(x,y):
    if x<y:return -1
    elif x>y:return 1
    else return 0

# 按字符第一个字母(不考虑大小写)排序

def strsort(x,y):
    x1=x[0].upper()
    y1=y[0].upper()
    if x1<y1:return -1
    elif x1>y1:return 1
    else return 0

lambda函数 (匿名函数)

快速定义单行单表达式操作并返回的最小函数, lambda函数是从lisp借来的.虽然说lambda函数,但其实他是个语句关键词而不是一个函数.

func=lambda 参数: 表达式 等价于def func(参数):return 表达式, 也可以直接(lambda 参数:表达式)(实参)直接调用.

lambda函数代码较简, 但只适用于单个表达式, 并且不能包含命令(直接return),但可接受多参数. 如果函数内容较复杂,建议用def func().lambda函数一个重要应用是在高阶函数中作为函数参数传入.


# 以下例子定义一个函数,若collapse为真,执行压缩字符串空白; 否则返回字符串.
# 其本事是函数,因为核心执行的是lambda部分.
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

偏函数

是一种高阶函数,其实就是可以重新设定指定函数某些参数的默认值,返回一个新的函数.

使用functools.partial(func,*args,**kw) 来进行重新定义默认值, 其中kw就是arg=val形式,而args就是一般的参数,会从原函数参数左边插入该些参数. 例如

int2 = functools.partial(int, base=2)
int2('1000000') #>>> 64

# 等价于 :
int('1000000', base=2) #>>> 64

# 也可在偏函数中像原函数一样指定值:
int2('1000000', base=10) #>>> 1000000

# 指定*args部分:
max10 = functools.partial(max,10);
# 传入参数后等价于max(10,5,6,7)
max10(5,6,7)  #>>>10

闭包和返回函数

返回函数就是将一个函数作为结果返回. 当返回的函数在一个函数内时(就是函数内的函数), 称之为闭包(closure), 此时相关参数和变量都保存在返回的函数中.

返回的函数是一个新的对象, 存有相应的信息.由于只是返回函数, 并没有执行返回函数内的返回结果, 只有在再次调用时才起效.

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum
f = lazy_sum(1, 3, 5, 7, 9)
f() #>>> 25

在返回函数返回多个闭包时,注意返回函数不要引用任何循环变量或者后续会变化的变量.

def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()
f1();f2();f3(); #>>> 9; 9; 9

### 没有预期结果原因是, 返回的是列表是三个闭包, 这三个闭包的值引用的是i, 而i的值在返回阶段才执行

# 正确写法:
def count():
    fs = []
    for i in range(1, 4):
        def f(j):
            def g():
                return j*j
            return g
        fs.append(f(i))
    return fs
f1, f2, f3 = count()
f1();f2();f3(); #>>> 1; 4; 9

装饰器 Decorator

在代码运行期间动态增加功能的方式,称之为“装饰器”。装饰器本质是高阶函数, 就是将函数作为参数进行相应运作. 装饰器在python中在函数/对象方法定义前使用@符号调用. 装饰器可以在函数运行前进行一些预处理, 例如检查类型等.

@dec1
@dec2(arg1,arg2)
def test(arg):
    pass

以上代码等于dec1(dec2(arg1,arg2)(test(arg)))

动态类和对象方法:

python动态语言,可以对类/对象直接添加新的属性和方法. 对类进行添加,所有实例都起效, 对某个实例添加, 只能对该实例起效,其余实例不受影响. 注意添加方法需要使用self,因为会传递实例本身.

class Student(object):pass
s1=Student();
s2=Student();
s1.hi=10; s1.hi; # 对实例添加新属性
# -> 10
s2.hi;
# -> 'Student' object has no attribute 'hi'
Student.hi=11; # 对类添加新属性
s1.hi; #实例不受新添加类属性影响
#-> 10
s2.hi; # 新属性对另一实例起效
#-> 11

def prints(self):print "Hello!";
def printss():print "Hi!";
s1.printss=printss; 
s1.printss    #-> <function __main__.printss>
s1.printss(); # 其实此时并不是绑定的方法,而只是调用一个函数.
# -> Hi!
s2.printss();
#-> 'Student' object has no attribute 'printss'
Student.printss=printss
s2.printss()
#-> printss() takes no arguments (1 given)
Student.prints=prints;
s2.prints  # 绑定的方法,会传递self
#-> <bound method Student.prints of <__main__.Student object at 0x050D6770>>
s2.prints()
#-> Hello!

使用MehodType函数可以也将函数绑定为类的方法. 第二个参数为None,第三个参数若为类, 则所有实例都起效; 也可以只绑定某个实例对象(第二个参数为实例,第三个参数为类或不填), 此时其余对象不具有该方法.

from types import MethodType
def set_score(self, score):
	self.score = score
s1=Student();s2=Stundet();
s1.MethodType(set_score, s1, Student)
s1.set_score(60),s1.score; #-> 60
s2.set_score(60); #-> AttributeError: 'Student' object has no attribute 'set_age'
Student.set_score = MethodType(set_score, None, Student)
s2.set_score(80);s2.score; #-> 80

限制类属性 __slots__:

__slots__ = ('name', 'age') 可以限制类属性只能有列出的来的几种. 添加或指定新属性将报错AttributeError.

__slots__只对当前类起效, 对子类无效. 若子类也定义了slots, 则子类运行的属性则是父类和子类的slots的合集.

对象方法变对象属性的装饰器@property和@*.setter

该装饰器是python内置的,是类中一个高级用法,作用是将一个方法名变成一个对象属性. 类需要继承于object相应的类.
构建相应@property def prop(self):return self._prop就可以直接obj.prop来将方法变成获取对象属性的调用形式.而相应@prop.setter def prop(self,value): self._prop=value 就可以实现obj.prop=value将方法转为对象属性的赋值.而且好处还可以在此加入属性的值的检查. obj._prop只是相应储存的储存地方,名字也是无限制的.
不定义setter而只定义property的话,该属性就是只读的不能修改的!!

例如:

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def 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

    @property
    def fail(self):
        return True if (self.score <60) else False
        # (self.score <60) and return True or return False

s = Student()
s.score = 60 # OK,实际转化为s.set_score(60)
s.score # OK,实际转化为s.get_score()
### 60
s.score = 9999
### Traceback (most recent call last):
###   ...
### ValueError: score must between 0 ~ 100!
s.fail
### False
s.fail=True
### Traceback (most recent call last)
### ...
### AttributeError: can't set attribute

__future__模块

__future__模块用来引入一些新版本的特性, 例如在2.x版本中引入3.x版本的特性.

  • from __future__ import unicode_literals 引入3.x版本中字符串特性, 使用该语句后,"str"就已经是unicode的,而2.x版本中的字符串则要使用b"str"来表示.
  • from __future__ import division 引入3.x中除法特性,3.x中除法默认是精确除法,2.x则是向下取整.例如10/32.x的是3,3.x是3.33333.使用该特性后就会采用3.x的特性, 而原有的除法要使用10//3来表示.

本博文已合并到Python语法汇总中, 不再更新.



◆ 本文地址: http://platinhom.github.io/2015/10/21/pyMedium/, 转载请注明 ◆

前一篇: Python:类和对象object
后一篇: Python:元类metaclass


Contact: Hom / 已阅读()
Source 类别: Coding  标签: Python