Python进阶课程

Shanshan yuan · 收录于 2023-12-06 19:59:02 · source URL

Python进阶课程

Python是动态语言。动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。
课程网址:python进阶

1.高阶函数

1. map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。

注意:map()函数不改变原有的 list,而是返回一个新的 list。

python中filter()函数

2. filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。

例如,要从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数,首先,要编写一个判断奇数的函数:

def is_odd(x):
    return x % 2 == 1

然后,利用filter()过滤掉偶数:

filter(is_odd, [1, 4, 6, 7, 9, 12, 17])

结果:[1, 7, 9, 17]

3.Python内置的 sorted()函数可对list进行排序:

sorted([36, 5, 12, 9, 21])

[5, 9, 12, 21, 36]

但 sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。

因此,如果我们要实现倒序排序,只需要编写一个reversed_cmp函数:

def reversed_cmp(x, y):
    if x > y:
        return -1
    if x < y:
        return 1
    return 0

#这样,调用 sorted() 并传入 reversed_cmp 就可以实现倒序排序:

>>> sorted([36, 5, 12, 9, 21], reversed_cmp)
[36, 21, 12, 9, 5]

4.python中返回函数

Python的函数不但可以返回int、str、list、dict等数据类型,还可以返回函数!

例如,定义一个函数 f(),我们让它返回一个函数 g,可以这样写:

def f():
    print 'call f()...'
    # 定义函数g:
    def g():
        print 'call g()...'
    # 返回函数g:
    return g

仔细观察上面的函数定义,我们在函数 f 内部又定义了一个函数 g。由于函数 g 也是一个对象,函数名 g 就是指向函数 g 的变量,所以,最外层函数 f 可以返回变量 g,也就是函数 g 本身。

调用函数 f,我们会得到 f 返回的一个函数:

>>> x = f()   # 调用f()
call f()...
>>> x   # 变量x是f()返回的函数:
<function g at 0x1037bf320>
>>> x()   # x指向函数,因此可以调用
call g()...   # 调用x()就是执行g()函数定义的代码

请注意区分返回函数和返回值:

def myabs():
    return abs   # 返回函数
def myabs2(x):
    return abs(x)   # 返回函数调用的结果,返回值是一个数值

返回函数可以把一些计算延迟执行。例如,如果定义一个普通的求和函数:

def calc_sum(lst):
    return sum(lst)

调用calc_sum()函数时,将立刻计算并得到结果:

>>> calc_sum([1, 2, 3, 4])
10

但是,如果返回一个函数,就可以“延迟计算”:

def calc_sum(lst):
    def lazy_sum():
        return sum(lst)
    return lazy_sum
调用calc_sum()并没有计算出结果,而是返回函数:
>>> f = calc_sum([1, 2, 3, 4])
>>> f
<function lazy_sum at 0x1037bfaa0>
对返回的函数进行调用时,才计算出结果:
>>> f()
10

由于可以返回函数,我们在后续代码里就可以决定到底要不要调用该函数。

5.python中闭包

在函数内部定义的函数和外部定义的函数是一样的,只是他们无法被外部访问:

def g():
    print 'g()...'

def f():
    print 'f()...'
    return g

将 g 的定义移入函数 f 内部,防止其他代码调用 g:

def f():
    print 'f()...'
    def g():
        print 'g()...'
    return g

但是,考察上一小节定义的 calc_sum 函数:

def calc_sum(lst):
    def lazy_sum():
        return sum(lst)
    return lazy_sum

注意: 发现没法把 lazy_sum 移到 calc_sum 的外部,因为它引用了 calc_sum 的参数 lst。

像这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。

闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。举例如下:

希望一次返回3个函数,分别计算1x1,2x2,3x3:
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()结果应该是1,4,9,但实际结果全部都是 9(请自己动手验证)。

原因就是当count()函数返回了3个函数时,这3个函数所引用的变量 i 的值已经变成了3。由于f1、f2、f3并没有被调用,所以,此时他们并未计算 i*i,当 f1 被调用时:

>>> f1()
9     # 因为f1现在才计算i*i,但现在i的值已经变为3

因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量。

装饰器的使用(decorator)
def log(f):
    def fn(*args, **kw):
        print ('call ' + f.__name__ + '()...')
        return f(*args, **kw)
    return fn
@log #@代表装饰器,使用的是上面的log(),参数f为function,也就是下面自己声明的函数
def add(x, y):#这一个函数的声明,其实就是上面函数的参数f
    return x + y
print(add(1, 2))#调用add,此时的add是装饰器的一个参数,会自动调用@后面对应的函数

对于一个装饰器函数,应该注意的是语法格式为

def 函数名(参数f/或者function)def fn(*args,**kw) #表示任意参数
 		.......
 		return f(*args,**kw)
 	......
 	return fn

其中装饰器的使用还有其他两种使用方法,详情见链接课程!

python中偏函数(functool.partial)

functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。

#比如,int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换:
int('12345')
12345
 使用偏函数类似于声明如下函数
def int2(x, base=2):
    return int(x, base)
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:

import functools
int2 = functools.partial(int, base=2)
int2('1000000')
64
int2('1010101')
85
python中继承一个类

如果已经定义了Person类,需要定义新的Student和Teacher类时,可以直接从Person类继承:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

定义Student类时,只需要把额外的属性加上,例如score:

class Student(Person):
    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        #必须加入上面一句话
        self.score = score

一定要用 super(Student, self).init(name, gender) 去初始化父类,否则,继承自 Person 的 Student 将没有 name 和 gender。

函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用__init__()方法,注意self参数已在super()中传入,在__init__()中将隐式传递,不需要写出(也不能写)

字典items()方法和iteritems()方法,是python字典的内建函数,分别会返回Python列表和迭代器。字典items()操作方法:

通俗的理解就是使用items()返回的是一个列表,而使用iteritems()返回的是一个相当于对象的类型数据,必须在使用list()转化成列表。

>>> x = {'title':'python web site','url':'www.iplaypy.com'}
>>> x.items()

[(‘url’, ‘www.iplaypy.com’), (‘title’, ‘python web site’)]
从结果中可以看到,items()方法是将字典中的每个项分别做为元组,添加到一个列表中,形成了一个新的列表容器。如果有需要也可以将返回的结果赋值给新变量,这个新的变量就会是一个列表数据类型。

>>> a=x.items()
>>> a
[('url', 'www.iplaypy.com'), ('title', 'python web site')]
>>> type(a)
<type 'list'>

dict iteritems()操作方法:

>>> f = x.iteritems()
>>> f
<dictionary-itemiterator object at 0xb74d5e3c>
>>> type(f)
<type 'dictionary-itemiterator'>    #字典项的迭代器
>>> list(f)
[('url', 'www.iplaypy.com'), ('title', 'python web site')]

字典.iteritems()方法在需要迭代结果的时候使用最适合,而且它的工作效率非常的高。

如果已知一个属性名称,要获取或者设置对象的属性,就需要用 getattr() 和 setattr( )函数了----只能应用于Class中,也就是所说的类上或者一个实例中。
python 3.*中已经没有了__div__,换成了__truediv__
class Rational(object):
    def __init__(self, p, q):
        self.p = p
        self.q = q

    def __add__(self, r):
        return Rational(self.p * r.q + self.q * r.p, self.q * r.q)

    def __sub__(self, r):
        return Rational(self.p*r.q - self.q*r.p, self.q*r.q)

    def __mul__(self, r):
        return Rational(self.p*r.p, self.q*r.q)

    def __truediv__(self, r): 
    #__truediv__
        return Rational(self.p*r.q , self.q*r.q)

    def __str__(self):
        g = gcd(self.p, self.q)
        return '%s/%s' % (self.p / g, self.q / g)
    __repr__ = __str__

# 求出最大公约数:使用简单的递归实现。
def gcd(a, b):
    if b == 0:
        return a
    return gcd(b, a % b)
r1 = Rational(1, 2)
r2 = Rational(1, 4)
print(r1 + r2)
print(r1 - r2)
print(r1 * r2)
print(r1 / r2)