Python进阶教学一

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


一、函数

1.高阶函数

  • 1.1 map
  • 1.2 reduce
  • 1.3 filter
  • 1.4 sorted
python 复制代码
# 1.1 map()函数:把一个函数作用到一个Iterable的东西上
# 参数:1.函数 2.Iterable
# 返回值类型:map object
# 举例:把平方作用到列表的每个值中
def f(x):
    return x * x
r = map(f,[1,2,3,4,5,6,7,8,9])
list(r)

>>>[1, 4, 9, 16, 25, 36, 49, 64, 81]

python 复制代码
# map()函数实际上就是不是运算规则抽象化了
# 把list的每个数字变成str
list(map(str,[1,2,3,4,5,6,7,8,9]))

>>>['1', '2', '3', '4', '5', '6', '7', '8', '9']

python 复制代码
# 1.2 reduce()函数:把一个函数累计作用到序列的下一个元素中
# reduce(f,[x1,x2,x3]) == f(f(x1,x2),x3)
# 举例,把[1,2,3]变成123
from functools import reduce
def fn(x,y):
    return x*10+y
reduce(fn,[1,2,3])

>>> 123

python 复制代码
# 1.3 filter函数:接收函数和序列,根据函数作用在序列的每个元素返回的True和False决定是否保留该元素
# 返回类型:Iterator
# 举例:只保留序列中的奇数
def is_odd(n):
    return n%2==1
list(filter(is_odd,[1,3,5,7,2,4,6,8]))

>>>[1, 3, 5, 7]

python 复制代码
# 把一个序列中的空字符去掉
def not_empty(s):
    return s.strip()
list(filter(not_empty, ['A', '', 'B', 'C', '  ']))

>>>['A', 'B', 'C']

python 复制代码
# sorted对list进行排序
sorted([32,12,-19,55,3])

>>>[-19, 3, 12, 32, 55]

python 复制代码
# 参数:key,接收自定义排序函数
# 举例:按照绝对值大小排序
sorted([32,12,-19,55,3],key=abs)

>>>[3, 12, -19, 32, 55]

python 复制代码
# 对于字符 是按照ASCII码进行排序
sorted(['sb','Sb','SB'])

>>>['SB', 'Sb', 'sb']

2.返回函数

  • 2.1 函数作为返回值
  • 2.2 闭包
python 复制代码
# 2.1 高阶函数出了可以接收函数作为参数,还可以把函数作为结果返回
# 一个可变参数的求和,如果不需要立刻求和,而是在后面的代码中,根据需要再计算
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum
# 调用的时候返回的是求和函数
f = lazy_sum(1,2,3,4)
f

>>> <function __main__.lazy_sum.<locals>.sum()>

# 调用函数f的时候,才是返回真正的求和结果
f()

>>>10

python 复制代码
# 在函数lazy_sum里面又定义了函数sum,内部函数可以引用外部函数的参数和局部变量
# lazy_sum返回了sum的时候,相关的参数和变量都保存在了返回函数中,就是闭包
# 每一次调用 返回的都是新的函数 但是传入的是相同的参数
f1 = lazy_sum(1,2,3,4)
f2 = lazy_sum(1,2,3,4)
f1 == f2

>>>False

python 复制代码
# 2.2 闭包
# 要注意返回的函数没有立刻执行,要再一次的调用才会执行
def count():
    fs = []
    for i in range(1,4):
        def f():
            return i * i
        fs.append(f)
    return fs
count()
f1,f2,f3 = count()
print(f1(),f2(),f3())
# 因为返回函数引用了i,并且并非立刻执行,3个函数都返回时,所以它引用的变量i已经变成3

>>>9 9 9

python 复制代码
# 如果一定要引用循环的变量,就应该再创建一个函数,绑定循环变量
def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1,4):
        fs.append(f(i))
    return fs
count()
f1,f2,f3 = count()
print(f1(),f2(),f3())

>>>1 4 9

3.匿名函数

python 复制代码
list(map(lambda x: x*x,[1,2,3]))

>>>[1, 4, 9]

python 复制代码
# 相当于
def f(x):
    return x * x

4.装饰器

python 复制代码
# 函数也是对象,所以可以赋值给变量,通过变量来调用函数
def now():
    print('2020-01-01')
f = now
f()

>>>2020-01-01

python 复制代码
# 想要增强now()的功能,在调用的前打印日志,有不改变函数本身的定义,这样动态增加功能的方法叫做装饰器
# 本质上是一个返回函数的高阶函数
def log(func):
    def wrapper(*args,**kw):
        print('call %s:'%func.__name__)
        return func(*args,**kw)
    return wrapper
# %%
@log
def now(x):
    print('2020-01-01')
now(1)
# %%

>>>

call now:

2020-01-01

python 复制代码
# @log 放在now函数之前 相当于
now = log(now)
python 复制代码
# decorator也要传入参数,需要编写一个decorator的高阶函数
def log(text):
    def decorator(func):
        def wrapper(*args,**kw):
            print('%s %s:'%(text,func.__name__))
            return func(*args,**kw)
        return wrapper
    return decorator
# %%
@log('execute')
def now():
    print('2020-01-01')
# %%
now()

>>>

execute now:

2020-01-01

python 复制代码
# 相当于
now = log('execute')(now)
# 先执行了log('execute'),返回了decorator函数,再调用返回函数,参数是now,返回的是wrapper
# 也就是原来的now函数变成了现在的wrapper函数了
now.__name__

>>>'wrapper'

python 复制代码
# 想要保持now的name的话 wrapper.__name__ = func.__name__
# 可以用装饰器 @functools.wraps(func)
import functools
def log(func):
    @functools.wraps(func)
    def wrapper(*args,**kw):
        print('call %s():' % func.__name__)
        return func(*args,**kw)
    return wrapper

# %%
@log
def now():
    print('2020-01-01')
# %%
now.__name__

>>>'now'

二、实例

1.类和实例

  • 1.1 基本定义
  • 1.2 创建实例
  • 1.3 绑定属性
  • 1.4 init
  • 1.5 数据封装
python 复制代码
# 1.1 基本定义
#  class + 类名 + (object) 即从哪个类继承下来的
class student(object):
    pass
python 复制代码
# 1.2 创建实例
# 类名+()
bart = student()
# 变量bart指向student类的实例,0x1064b1128是内存地址
bart
student

>>>

<main .student at 0x1064b1128>

main.student

python 复制代码
# 1.3 绑定属性
# 可以自由的给实例变量绑定属性
bart.name = 'sb'
bart.name

>>>'sb'

python 复制代码
# 1.4 __init__
# 类就像是模版 当我们想创建实例的时候就把一些属性写进去 可以用__init
class student(object):
    # self 就是实例本身
    def __init__(self,name,score):
        self.name = name
        self.score = score

bart = student('sb',0)
bart.name
bart.score

>>> 'sb' 0

python 复制代码
# 1.5 数据封装
# 比如一个函数本来就要用到学生类里面的数据,那当然就把函数放在类里面多好嘛
class student(object):
    def __init__(self,name,score):
        self.name = name
        self.score = score
    def print_score(self):
        print('%s:%s'%(self.name,self.score))

bart = student('sb',0)
bart.print_score()

>>>sb:0

2.限制访问

python 复制代码
# 按照上述的定义,外部代码还可以自由修改实例的属性
bart.score
bart.score = 100
bart.score

>>>

0

100

python 复制代码
# 我们更希望这些属性是私有的,不能被外部代码修改的
class student(object):
    def __init__(self,name,score):
        self.__name = name
        self.__score = score

    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))

bart = student('sb',0)
bart.__name
>>>
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-24-1e120ece361e> in <module>
----> 1 bart.__name

AttributeError: 'student' object has no attribute '__name'
python 复制代码
# 这么做又有一个问题,虽然外部代码不能修改实例的属性了。但是我们还是希望外部代码可以获得他的值
class student(object):
    def __init__(self,name,score):
        self.__name = name
        self.__score = score

    # 让外部可以获得属性的值
    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

    # 让外部可以改变属性的值
    def set_name(self,name):
        self.__name = name

    # 可以通过这样改变属性的方法来做参数检查,避免传入无效参数
    def set_score(self,score):
        if 0 <= score < 100:
            self.__score = score
        else:
            raise ValueError('bad score')

bart = student('sb',0)
bart.get_name()
bart.set_name('SB')
bart.get_name()

>>>

'sb'

'SB'

python 复制代码
bart.set_score(50)
bart.get_score()
>>>50

bart.set_score(250)
>>>
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-40-6cf87971f6eb> in <module>
----> 1 bart.set_score(250)

<ipython-input-31-e38b3fe7e472> in set_score(self, score)
     20             self.__score = score
     21         else:
---> 22             raise ValueError('bad score')

ValueError: bad score

3. 继承和多态

  • 3.1 继承
  • 3.2 子类的特性
  • 3.3 理解多态
python 复制代码
# 现在我们已经有一个动物class,一个run()方法打印
class Animal(object):
    def run(self):
        print("Animal is running...")
python 复制代码
# 3.1 继承
# 当我们需要具体的动物类时,可以从Animal继承
class cat(Animal):
    pass

class Dog(Animal):
    pass
python 复制代码
# 继承最大的好处就是子类有了父类的全部功能
dog = Dog()
dog.run()

>>>Animal is running...

python 复制代码
# 3.2 子类的特性
# 子类可以增加新的方法也可以对父类的方法进行改进
class Dog(Animal):
    # 改进父类方法
    def run(self):
        print('Dog is running...')

    # 新的方法
    def eat(self):
        print('Dog is eating...')

dog = Dog()
dog.run()
dog.eat()

>>>

Dog is running...

Dog is eating...

python 复制代码
# 3.3 理解多态
# 定义一个class,实际上就是定义了一种数据类型
a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型
python 复制代码
# c既是Dog也是Animal
# 就是说Dog可以看成是一个Animal
isinstance(c,Animal)
isinstance(c,Dog)

>>>

True

True

python 复制代码
# 理解多态的好处
class Animal(object):
    def run(self):
        print("Animal is running...")
    def eat(self):
        print('Anumal is eating...')

class Dog(Animal):
    def run(self):
        print('Dog is running...')
    def eat(self):
        print('Dog is eating...')


def run_eat(a):
    a.run()
    a.eat()
run_eat(Animal())

>>>

Animal is running...

Anumal is eating...

python 复制代码
run_eat(Dog())
# 多态的好处:传入的只要是Animal或者他的子类,就会自动调用实际类型的run()
# 调用的时候只管调用,新加一个子类的时候只要保证他继承的方法没写错
# 开闭原则:
# 对扩展开放:允许增加子类
# 对修改封闭:不需要修改类的run_eat()函数

>>>

Dog is running...

Dog is eating...

  • 静态语言:利用多态特性的时候,传入的对象必须严格的是Animal类或者他的子类
  • 动态语言:不要求严格的继承体系
    • 鸭子类型:一个对象只要看起来像鸭子,走路也像鸭子,就能被看作是鸭子
    • python:"file-like object"就是一种鸭子类型,某个对象有当前的这个函数方法,就可以当作是这个函数的对象了。

4.实例属性和类属性

python 复制代码
# 给实例绑定属性
# 1.通过实例变量 2.通过self变量
class student(object):
    def __init__(self,name):
        self.name = name

s = student('sb')
s.score = 0
python 复制代码
# 直接给类绑定一个类属性
class student(object):
    name = 'student'

# 创建实例
s = student()
# 这个时候实例没有name,所以会向上找类的name
s.name

>>>'student'

python 复制代码
# 打印类的属性
print(student.name)
>>>student

# 给实例绑定属性
s.name = 'sb'
print(s.name)
>>>sb

print(student.name)
>>>student
相关推荐
LyaJpunov几秒前
C++中move和forword的区别
开发语言·c++
程序猿练习生5 分钟前
C++速通LeetCode中等第9题-合并区间
开发语言·c++·leetcode
一名路过的小码农15 分钟前
C/C++动态库函数导出 windows
c语言·开发语言·c++
m0_6312704017 分钟前
标准c语言(一)
c语言·开发语言·算法
万河归海42818 分钟前
C语言——二分法搜索数组中特定元素并返回下标
c语言·开发语言·数据结构·经验分享·笔记·算法·visualstudio
Messiah___23 分钟前
【论文阅读】Slim Fly: A Cost Effective Low-Diameter Network Topology 一种经济高效的小直径网络拓扑
开发语言·php
充值内卷32 分钟前
WPF入门教学四 WPF控件概述
windows·ui·wpf
农民小飞侠1 小时前
python AutoGen接入开源模型xLAM-7b-fc-r,测试function calling的功能
开发语言·python
指尖流烟1 小时前
C#调用图表的使用方法
开发语言·c#
战神刘玉栋1 小时前
《程序猿之设计模式实战 · 观察者模式》
python·观察者模式·设计模式