006python面向对象编程入门“扫盲“(类继承|装饰器|生成器|迭代器|闭包|深浅拷贝|with上下文管理器|内建函数|魔术方法|联合类型注解|多态|设计模式|多线程编程|递归)初步整理

006python面向对象编程基础

1.1.装饰器

1.1.1. 装饰器基础

import functools

"""核心思想,函数就是参数,把函数当作参数传进去处理,使得函数增加新的功能再使用,不就是修饰一下"""


def outer(func):
    @functools.wraps(func)  # 使用原函数信息,否则返回装饰器信息
    def inner(*args, **kwargs):  # 多参数传递
        '''inter注释,#不显示'''
        print('before')
        res = func(*args, **kwargs)  # 多参数传递
        print('after')
        return res

    return inner


# 等价于,func=outer(func),outer返回inner --> 执行inner --> 中间实际执行func1原函数和添加功能 --> 返回原函数返回值
@outer
def func1(a1, a2):
    # func1注释
    '''三引号注释func.__doc__可以显示'''
    print('我func函数')
    value = (1, 2, 3, 4)
    return value


# @outer  # func=outer(func)
def func2():
    print('我func函数')
    value = (1, 2, 3, 4)
    return value


@outer  # func=outer(func)
def func3():
    print('我func函数')
    value = (1, 2, 3, 4)
    return value


if __name__ == '__main__':
    func1(5, a2=8)
    print(func1.__name__)  # 函数名,装饰器添加@functools.wraps(func)  # 使用原函数信息,否则返回装饰器信息
    print(func1.__doc__)  # 函数注释
    print(func2.__name__)
    print(func2.__doc__)
    print(func3.__name__)
    print(func3.__doc__)
    pass
before
我func函数
after
func1
三引号注释func.__doc__可以显示
func2
None
func3
None

1.1.2.装饰器中的闭包理解

def a0():
    """必报的简单理解"""
    def g_m_f(n):
        def m(x):
            return n * x

        return m

    double = g_m_f(2)(4)  # m(4) -> 2*4
    triple = g_m_f(3)  # m
    print(double)
    print(triple(3))  # m(3) -> 3*3


def a1():
    """函数当作参数传递"""
    def func():
        print('我func函数')
        value = (1, 2, 3, 4)
        return value

    def outer(origin):
        def inter():
            print('before')
            res = origin()
            print('after')
            return res

        return inter

    func = outer(func)
    result = func()
    print(result)


def a2():
    """用装饰器代替上面"""
    def outer(origin):
        def inter():
            print('before')
            res = origin()
            print('after')
            return res

        return inter

    @outer  # func=outer(func)
    def func():
        print('我func函数')
        value = (1, 2, 3, 4)
        return value

    result = func()
    print(result)


if __name__ == '__main__':
    a0()
    # a1(),a2(),效果是相同的,说明装饰器<=>原函数=装饰器(原函数)
    a1()
    a2()
8
9
before
我func函数
after
(1, 2, 3, 4)
before
我func函数
after
(1, 2, 3, 4)

1.1.3.多装饰器装饰一个函数

# 运行到装饰器直接装饰,然后函数就变过了,等到执行时依据装饰时候的线路反向执行打印
print('a')


def makeBlod(f):
    print('--1')  # 3

    def wrapped():
        print('--2')  # ---1
        return '<b>' + f() + '</b>'

    print('--3')  # 4
    return wrapped


print('b')


def makeItalic(f):
    print('--4')  # 1

    def wrapped():
        print('--5')  # ---2
        return '<i>' + f() + '</i>'

    print('--6')  # 2
    return wrapped


print('c')


# 执行到这里开始装饰函数,顺序如上面标注1...
@makeBlod  # <=> t=makeBlod(makeItalic(t)),后装饰,调用t()时先执行
@makeItalic  # <=> t=makeItalic(t),先装饰,调用t()时后执行
def t():
    print('--7')  # ---3
    return 'hello world'  # ---4


print('d')
# 开始执行被装饰的函数,执行顺序如上面---1...
print(t())
a
b
c
--4
--6
--1
--3
d
--2
--5
--7
<b><i>hello world</i></b>

1.1.4.带有参数的装饰器

import time


def outer1(timeout=0):
    # 3层函数的闭包
    print('---2---')

    def outer2(f):
        print('---4---')

        def inner():
            print('---7---')
            time.sleep(timeout)
            ret = f()
            print('---8---')
            return ret

        print('---5---')
        return inner

    print('---3---')
    return outer2


print('---1---')


# <=> @outer2,timeout=2,print_hello=outer1(2)(print_hello)=outer2(print_hello)=inner
@outer1(2)
def print_hello():  # <=> print_hello=outer2(print_hello)
    print('hello world')
    return 'okk'


print('---6---')
print(print_hello())
print('---9---')
---1---
---2---
---3---
---4---
---5---
---6---
---7---
hello world
---8---
okk
---9---

1.1.5.类装饰函数

from functools import wraps


class Test(object):
    """调用类就直接执行,初始化自动执行__init__,__call__,不用写具体函数方法"""

    def __init__(self, f):
        print('--1--', f)
        self.f = f

    def __call__(self):
        print('--2--')
        self.f()


print('------------')


@Test  # a1=Test(a1),_init__ :接收被装饰函数 __call__ :实现装饰逻辑
def a1():
    print('666')


a1()  # a1成为实例对象,实际调用的是__call__方法
print('下面带有参数的类装饰器')  # 带有参数的类装饰器


class Test1(object):
    def __init__(self, num):
        print('--1--', num)
        self.num = num

    @wraps  # 添加后返回函数信息
    def __call__(self, func):
        print('--2--')
        self.func = func
        return self.y

    def y(self):
        print('--3--')
        self.func()
        print('--4--')


@Test1(100)  # a2=实例对象(a2),类加()默认返回call方法的返回值y函数地址,a2=y(a2),__init__ :不再接收被装饰函数,而是接收传入参数。 __call__ :接收被装饰函数,实现装饰逻辑
# 当多个参数时,func不是第一个,就需要用到偏函数
def a2():
    print('666')


print(
    '===========',
    type(a2),  # <class 'method'>,添加@wraps变为<class 'function'>
    sep='\n')

a2()  # a2成为实例对象,实际调用的是__call__方法


def a3():
    """用偏函数传递参数"""
    class Test:
        def __init__(self, num, func):
            self.num = num
            self.func = func

        def __call__(self, *args, **kwargs):
            print(self.num)
            return self.func(*args, **kwargs)

    def delay(num):
        return functools.partial(Test, num)  # <=>Test(num, )

    @delay(num=2)
    # @Test(2, )  # add怎么传进去
    def add(a, b):
        return a + b

    # add = Test(2, add)  # 上面等价于这个
    add(4, 6)


a3()
------------
--1-- <function a1 at 0x000001B175813520>
--2--
666
下面带有参数的类装饰器
--1-- 100
===========
<class 'function'>
666
2

1.1.6.函数装饰类

def decorater(cls):  # 传入一个类即cls
    cls.person_name = '小明'  # 设置一个类属性
    return cls  # 返回这个被装饰过的类


@decorater  # person=decorater(person)
class person:
    pass


m = person()
print(m.person_name)
小明

1.1.7.类装饰类

class person:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('-----1-----')
        res = self.func(*args, **kwargs)
        return res


@person  # boss=person(boss)
class boss:
    def test(*args):
        print('-----2-----')


jack = boss()  # 实例化
print('-----3-----')
jack.test()
-----1-----
-----3-----
-----2-----

1.1.8.装饰器常见使用

"""装饰器的使用,网站验证,函数执行时间装饰,批量装饰等
下面flask没法执行,仅仅举例子"""


def flask_decorater():
    from flask import Flask

    app = Flask(__name__)

    def outer(func):
        def inner(*args, **kwargs):
            # 判断网站是否登录,未登录返回登陆界面
            res = func(*args, **kwargs)
            return res

        return inner

    def index():
        return '首页'

    @outer
    def info():
        return '用户中心'

    @outer
    def order():
        return '订单中心'

    def login():
        return '登陆页面'

    app.add_url_rule('/index/', view_func=index)
    app.add_url_rule('/info/', view_func=info)
    app.add_url_rule('/order/', view_func=order)
    app.add_url_rule('/login/', view_func=login)
    app.run()

1.2.生成器

1.2.1.认识生成器yield

def hello():
    """"yield每次返回一个,然后函数停止执行,并且记录位置和数据,下次调用接着执行"""
    print('step1')
    yield 1
    print('step2')
    yield 2
    print('step3')
    yield 3
    print('step4')
    yield 4


g = hello()
res = next(g)
print(res)
res = next(g)
print(res)
res = next(g)
print(res)
res = next(g)
print(res)

# print(hello())

# for res in g:
#     print(res)
step1
1
step2
2
step3
3
step4
4

1.2.2.生成器基本用法next

# 常规实现
num = 0
x = 0
y = 0
points = []
while num < 5:
    y = x * 2 + 1
    points.append((x, y))
    x = y
    num += 1
print(points)

print('-' * 15, '生成器')


# 迭代器的使用
class Points(object):
    def __init__(self):
        # 初始化一个空的点列表,以及初始的x值、k值和b值
        self.point_list = []
        self.x = 0
        self.k = 2
        self.b = 1

    def __iter__(self):
        # 使Points类成为一个迭代器。返回当前实例(self)
        return self

    def __next__(self):
        # 迭代器一定可以next
        # 定义了如何从迭代器中取出下一个元素。这里的计算公式temp_y = self.k * self.x + self.b用于生成新的y值,然后将(x, y)对添加到点列表中,并更新x的值为新的y值
        # temp_y = 2 * self.x + 1
        temp_y = self.k * self.x + self.b
        self.point_list.append((self.x, temp_y))
        self.x = temp_y
        return self.point_list

    def change_k_b(self, k, b):
        # 允许修改k和b的值
        self.k = k
        self.b = b


# 代码创建了一个Points的实例points,并通过iter(points)得到一个指向该实例的迭代器points_iter。使用next(points_iter)从迭代器中取出下一个元素
points = Points()
points_iter = iter(points)  # 创建迭代器对象
print(next(points_iter))
print(next(points_iter))
print(next(points_iter))
print(next(points_iter))
print(next(points_iter))

print(next(points))  # 直接在points对象上调用next()
print(next(points))
print(next(points))
print(next(points))
print(next(points))
points.change_k_b(3, 2)
print(next(points))
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31)]
--------------- 生成器
[(0, 1)]
[(0, 1), (1, 3)]
[(0, 1), (1, 3), (3, 7)]
[(0, 1), (1, 3), (3, 7), (7, 15)]
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31)]
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31), (31, 63)]
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31), (31, 63), (63, 127)]
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31), (31, 63), (63, 127), (127, 255)]
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31), (31, 63), (63, 127), (127, 255), (255, 511)]
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31), (31, 63), (63, 127), (127, 255), (255, 511), (511, 1023)]
[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31), (31, 63), (63, 127), (127, 255), (255, 511), (511, 1023), (1023, 3071)]

1.2.3.生成器两种类型

# 注意这里不要运行
# nums = [x for x in range(500000000000000)]  # 先生成后打印,内存危险
# print(type(nums))
# print(nums)
# for num in nums:
#     print(num)

# 第1种生成器,数据状态一直被记录着

import time
nums2 = (x for x in range(3))  # 生成一个输出一个,内存不占用太多,只能被调用3次
print(type(nums2))  # <class 'generator'>
print(nums2)  # <generator object <genexpr> at 0x000001AC27927610>
# for num in nums2:
#     print(num)

print(next(nums2))  # 0
# print(next(nums2))#1
# print(next(nums2))#2
# print(next(nums2))  # ,没有就StopIteration异常

num3 = list(nums2)  # 可以转化为列表,[]
print(num3)

# 斐波那契数列
print('斐波那契数列', '-' * 50)
num4 = 1
num5 = 1
print('第1个斐波那契数列:', num4)
num4, num5 = num5, num4 + num5
print('第2个斐波那契数列:', num4)
num4, num5 = num5, num4 + num5
print('第3个斐波那契数列:', num4)
num4, num5 = num5, num4 + num5
print('第4个斐波那契数列:', num4)
num4, num5 = num5, num4 + num5
print('第5个斐波那契数列:', num4)


# 迭代器
class FeiIterator(object):
    def __init__(self):
        self.num4 = 1
        self.num5 = 1

    def __iter__(self):
        return self

    def __next__(self):
        tem_num4 = self.num4
        self.num4, self.num5 = self.num5, self.num4 + self.num5
        return tem_num4


fei = FeiIterator()
print(next(fei))
print(next(fei))
print(next(fei))
print(next(fei))
print(next(fei))
print('-' * 80)
# for i in fei:  # 可以直接遍历,小心,永无止境
#     print(i)
#     time.sleep(1)

# 第二种yield生成器
print('-' * 50, '函数生成器')


def fib_generator():
    print('-1-' * 8)
    num4 = 1
    num5 = 1
    while True:
        print('-2-' * 8)
        tem_num = num4
        num4, num5 = num5, num4 + num5
        # return tem_num  # 每次调用num4,num5,被重置为
        yield tem_num  # 返回生成器对象和next()值,<generator object fib_generator at 0x0000014972A8A3B0>
        # 只要存在yield就是生成器,yield执行完后暂停并不终止,下次next继续执行
        print('-3-' * 8)


print('--fib_generator()--')
# <generator object fib_generator at 0x000001AC28E2CBA0>,返回的是生成器对象,不是生成器的值,每次返回一个对象
print(fib_generator())
print(fib_generator())
print(fib_generator())
print(fib_generator())
print('--next(fib_generator())--')
print(next(fib_generator()))  # 没反应,相当于函数每次直接重新调用,新对象的next不就是第一次嘛
print(next(fib_generator()))
print(next(fib_generator()))
# 必须创建生成器对象,才能next
print('--next(fib)--')
fib = fib_generator()
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))

# 多个yield,return
print('--多个yield--'*10)


def fib_g():
    n1 = 1
    n2 = 1
    tem_n1 = n1
    n1, n2 = n2, n1 + n2
    print('-a-' * 8)
    # 2.调用next()时,遇到return,返回错误,StopIteration,返回错误,并把return内容添加到异常中存储起来
    # return None
    yield tem_n1
    print('-b-' * 8)
    tem_n1 = n1
    n1, n2 = n2, n1 + n2
    print('-c-' * 8)
    yield tem_n1
    print('-d-' * 8)
    tem_n1 = n1
    n1, n2 = n2, n1 + n2
    print('-e-' * 8)
    yield tem_n1
    print('-f-' * 8)
    print('none yield')
    # 1.调用next()时没有yield了,返回错误,StopIteration
    # 2.调用next()时,遇到return,返回错误,StopIteration,返回错误,并把return内容添加到异常中存储起来
    return "生成了三个斐波那契数字"


f = fib_g()
print(next(f))
print(next(f))
print(next(f))
# print(next(f))
try:
    print(next(f), '正常内容')

except StopIteration as ret:  # ret是异常对象,中有value属性封装了return内容
    print(ret.value, '异常')
<class 'generator'>
<generator object <genexpr> at 0x000001B17584CA50>
0
[1, 2]
斐波那契数列 --------------------------------------------------
第1个斐波那契数列: 1
第2个斐波那契数列: 1
第3个斐波那契数列: 2
第4个斐波那契数列: 3
第5个斐波那契数列: 5
1
1
2
3
5
--------------------------------------------------------------------------------
-------------------------------------------------- 函数生成器
--fib_generator()--
<generator object fib_generator at 0x000001B17584CD60>
<generator object fib_generator at 0x000001B17584CD60>
<generator object fib_generator at 0x000001B17584CD60>
<generator object fib_generator at 0x000001B17584CD60>
--next(fib_generator())--
-1--1--1--1--1--1--1--1-
-2--2--2--2--2--2--2--2-
1
-1--1--1--1--1--1--1--1-
-2--2--2--2--2--2--2--2-
1
-1--1--1--1--1--1--1--1-
-2--2--2--2--2--2--2--2-
1
--next(fib)--
-1--1--1--1--1--1--1--1-
-2--2--2--2--2--2--2--2-
1
-3--3--3--3--3--3--3--3-
-2--2--2--2--2--2--2--2-
1
-3--3--3--3--3--3--3--3-
-2--2--2--2--2--2--2--2-
2
-3--3--3--3--3--3--3--3-
-2--2--2--2--2--2--2--2-
3
-3--3--3--3--3--3--3--3-
-2--2--2--2--2--2--2--2-
5
-3--3--3--3--3--3--3--3-
-2--2--2--2--2--2--2--2-
8
--多个yield----多个yield----多个yield----多个yield----多个yield----多个yield----多个yield----多个yield----多个yield----多个yield--
-a--a--a--a--a--a--a--a-
1
-b--b--b--b--b--b--b--b-
-c--c--c--c--c--c--c--c-
1
-d--d--d--d--d--d--d--d-
-e--e--e--e--e--e--e--e-
2
-f--f--f--f--f--f--f--f-
none yield
生成了三个斐波那契数字 异常

1.2.3.生成器中的send

'''
如果想让生成器继续向下运行,可以用next或send
同:继续向下运行;遇不见yield产生异常
异:next只会继续运行,什么也不传入,send还可以传入数据,代替yield语句
'''


def generator_test():
    while True:
        print('--1--')
        num = yield 100
        print('--2--', 'num=', num)


g = generator_test()
# print(next	(g))
# print(next	(g))
# print(next	(g))

print(g.send(None))  # send()一般不在开头使用,之前用next(),首次使用传入none
print(g.send(11))
print(g.send(22))
print(g.send(33))

# 写个生成器


def create_point():
    x = 0
    while True:
        tem = x
        y = 2 * x + 1
        x = y
        # return y
        yield tem, y


def create_point1():
    x = 0
    while True:
        y = 2 * x + 1
        # return y
        yield x, y
        x = y


def create_point2():
    x = 0
    k = 2
    b = 1
    while True:
        y = k * x + b
        tem = yield x, y
        if tem:
            k, b = tem
        x = y


# 创建一个生成器对象
point = create_point()
print(next(point))
print(next(point))
print(next(point))
print(next(point))


point1 = create_point1()
print(next(point1))
print(next(point1))
print(next(point1))
print(next(point1))
print('上两生成器一样', '='*100)

point2 = create_point2()
print(next(point2))
print(next(point2))
print(point2.send((3, 2)))  # 传入参数,改变生成器内部参数
print(next(point2))
print(next(point2))
print(point2.send((1, 0)))
print(next(point2))
print(next(point2))
--1--
100
--2-- num= 11
--1--
100
--2-- num= 22
--1--
100
--2-- num= 33
--1--
100
(0, 1)
(1, 3)
(3, 7)
(7, 15)
(0, 1)
(1, 3)
(3, 7)
(7, 15)
上两生成器一样 ====================================================================================================
(0, 1)
(1, 3)
(3, 11)
(11, 35)
(35, 107)
(107, 107)
(107, 107)
(107, 107)

1.3.迭代器

1.3.1.迭代器基本概念iter|next

import collections.abc
a1 = [1, 2, 3, 4]
a2 = 'asdfghj'
a3 = {'dsd': 43, 34: 32, (2, 4): 'fdds', 'sf': 32}
a4 = ('q', 4, "re", [33, 00])

print(isinstance(a1, collections.abc.Iterable),  # 判断是否可以迭代,都是True,都可以迭代
      isinstance(a2, collections.abc.Iterable),
      isinstance(a3, collections.abc.Iterable),
      isinstance(a4, collections.abc.Iterable))

print(type(a1))  # <class 'list'>
a1_iter = iter(a1)  # 迭代器
print(type(a1_iter))  # <class 'list_iterator'>

n1 = next(a1_iter)
print(n1)
n2 = next(a1_iter)
print(n2)
n3 = next(a1_iter)
print(n3)
n4 = next(a1_iter)
print(n4)
# n5=next(a1_iter)
# print(n5)
try:
    n5 = next(a1_iter)
    print(n5)
except StopIteration as ret:
    print(ret)
    print(ret.value)  # 异常是空的

# for循环可以用iter()和next()实现,for自带StopIteration处理
print('-' * 100)
for i in a1:
    print(i)

print('-3-' * 50)
a2_iter = iter(a1)  # 用迭代器尝试遍历
while True:
    try:
        a = next(a2_iter)
        print(a)
    except StopIteration as ret:  # 异常处理
        print(ret)
        print(ret.value)
        break

# 自定义迭代器
print('自定义迭代器-------------------------')


class MyList(object):
    def __init__(self):
        self.container = []

    def add(self, item):
        self.container.append(item)

    def __iter__(self):
        # 1.只有加这个方法,才可迭代
        # 2.iter()自动调用执行后返回一个迭代器
        return MyIterator(self)  # 返回迭代器实例,把实例本身传到下面的类中当参数,


class MyIterator(object):
    '''创建一个上面使用的迭代器'''

    def __init__(self, mylist):
        self.mylist = mylist
        # 记录当前访问到的位置
        self.current = 0

    def __next__(self):
        # 1.标记类所创建的对象一定是迭代器(有__iter__和__next__才是迭代器)
        # 2.next()自动调用执行,返回数据
        if self.current < len(self.mylist.container):
            num = self.mylist.container[self.current]
            self.current += 1
            return num
        else:
            raise StopIteration  # 抛出异常

    def __iter__(self):
        return self


mylist = MyList()
mylist.add(11)
mylist.add(12)
mylist.add(13)
mylist_iter = iter(mylist)
print(mylist_iter)
print(isinstance(mylist, collections.abc.Iterable),
      isinstance(mylist, collections.abc.Iterator),
      isinstance(mylist_iter, collections.abc.Iterable),
      isinstance(mylist_iter, collections.abc.Iterator))
True True True True
<class 'list'>
<class 'list_iterator'>
1
2
3
4

None
----------------------------------------------------------------------------------------------------
1
2
3
4
-3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3--3-
1
2
3
4

None
自定义迭代器-------------------------
<__main__.MyIterator object at 0x000001B175807520>
True False True True

1.3.2.迭代器框架

'''
可以for循环的,一定是iterable
next()的,一定是iterator
dict,str,list,tuple等是iterable,不是iterator,可以iter()出iterator
'''
print('自定义迭代器--------------')


class MyList(object):
    def __init__(self):
        self.container = []
        self.current = 0

    def add(self, item):
        self.container.append(item)

    def __iter__(self):
        # 1.只有加这个方法,才可迭代
        # 2.iter()自动调用执行后返回一个迭代器
        return self  # 返回迭代器

    def __next__(self):
        # 1.标记类所创建的对象一定是迭代器(有__iter__和__next__才是迭代器)
        # 2.next()自动调用执行,返回数据
        if self.current < len(self.container):
            num = self.container[self.current]
            self.current += 1
            return num
        else:
            # self.current = 0  # 解决第二次for循环没数据
            raise StopIteration  # 抛出异常,不用为了符合for循环终止条件,不用None


if __name__ == '__main__':
    mylist = MyList()
    mylist.add(11)
    mylist.add(12)
    mylist.add(13)
    mylist_iter = iter(mylist),  # 迭代器使用会记录位置,好像下面只能使用一次

    # list ,tuple可以接收可迭代对象
    mylist_list = list(mylist_iter)
    print(mylist_list)

    for i in mylist_iter:
        print(i)

    print('-' * 9)
    # for i in mylist_iter:
    #     print(i)
    mylist_list = list(mylist_iter)
    print(mylist_list)
自定义迭代器--------------
[<__main__.MyList object at 0x000001B175807DF0>]
<__main__.MyList object at 0x000001B175807DF0>
---------
[<__main__.MyList object at 0x000001B175807DF0>]

1.4.闭包

1.4.1.类中call

# 面向对象
class Person(object):
    def __init__(self, name):
        self.name = name

    def say(self, content):
        print(f'({self.name}):{content}')
        print('(%s):%s' % (self.name, content))

    def __call__(self, x):  # 实例对象(),p()自动调用call方法,否则'Person' object is not callable
        print(x)


p1 = Person('jack')
p2 = Person('bob')
p1.say('111')
p2.say('222')
p1('-------------------------__call__方法展示')
# 闭包
print('-' * 20, '闭包')  # 实例对象(),p()自动调用call方法,否则'Person' object is not callable


def who(name):
    """
    闭包:
    1.必须函数嵌套,外部函数返回内部函数地址
    2.内部函数使用外部函数参数
    3.内部函数可能执行或者修饰传入的函数
    """
    def con(content):
        print('(%s):%s' % (name, content))
    return con


# 创建闭包对象,相互独立,每个闭包占用内存
p3 = who('j')  # 等价于con,name='j'
p4 = who('b')
p3('111')  # con('111'),name='j'
p4('222')
print(p3)
# del p3# 释放内存
p3('333')  # con('333'),name='j'
(jack):111
(jack):111
(bob):222
(bob):222
-------------------------__call__方法展示
-------------------- 闭包
(j):111
(b):222
<function who.<locals>.con at 0x000001B1758752D0>
(j):333

1.4.2.闭包nonlocal声明

num = [1, 2, 3, 4]
print(num)


def c(n):
    # 函数直接修改传入的变量,原数据也改
    for i in range(30, 41):
        n.append(i)
    return n


s = c(num)
print(s)
print(num)


def d():
    # 可以直接修改函数外变量s,不用声明
    m = s.append('ddd')
    return s


print(d())
print(s)


def outer(m=0):
    def inner():
        nonlocal m  # 闭包内部函数不用nonlocal声明外部函数变量,不能修改,报错
        m += 1
        return m
    return inner


# 创建闭包对象
con = outer(5)  # 等价于inner,m=5
print(con())  # inner(),m=5
print(con())  # inner(),m=6
print(con())  # inner(),m=7

'''
对象:可以有n个属性+n个方法
闭包:可以有n个变量+n(一般1个)个函数
'''
print('-' * 60)


def g(k, b):
    def g1(x):
        y1 = k * x + b
        return y1

    def g2(x):
        y2 = 2 * k * x + b
        return y2
    return g1, g2


t = g(2, 3)
print(t[0](2))
print(t[1](3))
[1, 2, 3, 4]
[1, 2, 3, 4, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
[1, 2, 3, 4, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
[1, 2, 3, 4, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 'ddd']
[1, 2, 3, 4, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 'ddd']
6
7
8
------------------------------------------------------------
7
15

1.4.3.闭包中函数,类当作参数传递的理解

'''
函数,匿名函数,闭包,对象,当作实参的区别
'''


def test(x):
    pass


def a():
    pass


test(a)  # 传递函数a的引用到test中,传递功能没有数据


def b(x):
    return x * 2


test(b)  # 传递匿名函数b的引用到test中,传递功能没有数据


def person(name):
    def say(content):
        print(name, content)
    return say


c = person('张三')
test(c)  # 传递say方法,和name数据到test


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


d = person('张三')
test(d)  # 传递对象的实例d的引用到test中,传递功能,和name属性数据

1.5.深浅拷贝

1.5.1.copy的运用|id内存|可变不可变类型的理解

import copy
'''
总结:
1.=,是引用复制,指向地址相同,is相同type和内容一定相同即==成立,反之不一定
2.copy.copy()
    2.1,顶层是不可变数据类型,就是引用复制
    2.2,顶层数据类型可变,就是浅拷贝,只拷贝最顶层
3.copy.deepcopy(),一定是递归拷贝,全部复制
'''
a = [1, 2, 3]
b = [1, 2, 3]
c = b  # 引用的复制<==>浅拷贝,地址相同
d = copy.copy(b)  # b,d地址不同
e = [a, b]
f = copy.copy(e)  # 浅拷贝,只拷贝最(外)顶层,ef地址不同,但所用ab相同
g = copy.deepcopy(e)  # 全部拷贝一份,ge不同,ab和原来也不同
# b.append(6)  # q浅拷贝跟着变,深拷贝不变
print(a, id(a))
print(b, id(b))
print(c, id(c))
print(d, id(d))
print(e, id(e), id(e[0]), id(e[1]))
print(f, id(f), id(f[0]), id(f[1]))
print(g, id(g), id(g[0]), id(g[1]))
print(a == b)  # True,仅判断数据是否相同
print(a is b)  # False,判断地址是否相同
print(c == b)
print(c is b)
print(d == b)
print(d is b)
print('------其他拷贝方式-----' * 10)
# 切片
h = e[:]  # <=>h=copy.copy(b)
print(h, e)
b.append(7)  # 改变b,he都变
print(h, e)
print(id(b))
# 字典
i = {
    'name': 'jack',
    'age': 18,
    'cars': [100, 200, 300]
}

# 这种方式创建字典可读性强,等价于j={},集合也是{}
j = dict(name='jack', age=18, cars=[100, 200, 300], )
print(i, j, sep='\n')
k = dict.copy(j)  # 浅拷贝
j['cars'].append(400)
print(j, k, id(j), id(k), id(j['age']), id(k['age']), sep='\n')
print('-----------深浅拷贝总结' * 10)
# 1.copy.copy()只检测最外层数据,最外层是可变数据类型时,是浅拷贝,不可变的直接指向地址,拷都不拷
l = [4, 5, 6]
m = (7, 8, 9)  # 元组不可变是结构不可变,即引用地址的不可变,一级元素的地址不能变,二级元素地址可以变
l1 = copy.copy(l)
m1 = copy.copy(m)
print(id(l), id(l1), id(l[0]), id(l[1]), id(l1[0]), id(l1[1]))
print(id(m), id(m1), id(m[0]), id(m[1]), id(m1[0]), id(m1[1]))
# m[0]=1 #不可更改
l[0] = 99
print(l, id(l), id(l[0]))  # 整形为不可变数据类型,所以id(l[0])变了,id(l)没变

"""拓展,Python的字符串驻留机制,字符串中出现了非标识符允许的字符的时候才不采取驻留有[0-9] [a-z] [A-Z]和"_"(下划线),节省内存指向统一地址,
所谓可变数据类型其实更改后内存地址不变而已,可变的理解为,更改数据,原地址内存释放,重新分配内存地址创建新的对象"""
z1 = 'nice'
z2 = 'nice'
z3 = 'nice'
print(id(z1), id(z2), id(z3))  # id相同
[1, 2, 3] 1861692808896
[1, 2, 3] 1861692831680
[1, 2, 3] 1861692831680
[1, 2, 3] 1861692809216
[[1, 2, 3], [1, 2, 3]] 1861692808768 1861692808896 1861692831680
[[1, 2, 3], [1, 2, 3]] 1861692809408 1861692808896 1861692831680
[[1, 2, 3], [1, 2, 3]] 1861692809152 1861692808960 1861692809792
True
False
True
True
True
False
------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----------其他拷贝方式-----
[[1, 2, 3], [1, 2, 3]] [[1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3, 7]] [[1, 2, 3], [1, 2, 3, 7]]
1861692831680
{'name': 'jack', 'age': 18, 'cars': [100, 200, 300]}
{'name': 'jack', 'age': 18, 'cars': [100, 200, 300]}
{'name': 'jack', 'age': 18, 'cars': [100, 200, 300, 400]}
{'name': 'jack', 'age': 18, 'cars': [100, 200, 300, 400]}
1861692811392
1861691370432
1861631148816
1861631148816
-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结-----------深浅拷贝总结
1861692810048 1861692680704 1861631148368 1861631148400 1861631148368 1861631148400
1861686525120 1861686525120 1861631148464 1861631148496 1861631148464 1861631148496
[99, 5, 6] 1861692810048 1861631151408
1861680288304 1861680288304 1861680288304

1.5.2.深浅拷贝对象属性测试

import copy


class Birthday:
    """docstring for Birthday"""

    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day


class Person:
    """docstring for Person"""

    def __init__(self, name, birthday):
        self.name = name
        self.birthday = birthday


b1 = Birthday(2001, 2, 12)
p1 = Person("李$%#3", b1)  # 类的实例可以当作参数传递,上面分析过了
b2 = Birthday(2000, 5, 12)
p2 = Person("李四", b2)
p3 = p1
p4 = copy.copy(p1)
p5 = copy.deepcopy(p1)
print(id(b1), id(b2))
print(p1 == p2, id(p1), id(p2), id(p3), id(p4), id(p5),
      type(p1), type(p2))  # 类型相同,但是地址不同,是不同的实例对象(理解为内容不同吧)
print(p1 == p3)
print(p1 == p4)
print(p1 == p5)
print(p1.name == p2.name, id(p1.name), id(p2.name),
      type(p1.name), type(p2.name))  # 地址不同(对象都不同),类型str内容相同
print(p1.name == p3.name, id(p3.name))
print(p1.name == p4.name, id(p4.name))  # 最外层实例被拷贝了,实例属性任然是同一地址
print(p1.name == p5.name, id(p5.name))  # 最外层实例被拷贝了,但是实例属性任然是同一地址!
print(p1.birthday == p2.birthday, id(p1.birthday), id(p1.birthday.day),
      id(p2.birthday), id(p2.birthday.day), type(p1.birthday), type(p1.birthday.day))  # 对象不同,地址不同
print(p1.birthday == p3.birthday, id(p3.birthday), id(p3.birthday.day))
print(p1.birthday == p4.birthday, id(p4.birthday), id(p4.birthday.day))  # 指向原地址
print(p1.birthday == p5.birthday, id(p5.birthday),
      id(p5.birthday.day))  # int为不可变数据类型
"""上面深拷贝p5.name没变,p5.birthday变了我也不清楚什么原因,p5.birthday.day没变指向原地址,
暂时理解为深拷贝类的实例可以从新创建类,但是属性需要新的参数传入,没有所以指向引用"""

a = 3
b = copy.deepcopy(a)
print(id(a), id(b))
1861692463456 1861692462304
False 1861692457072 1861692469888 1861692457072 1861692471040 1861692464800 <class '__main__.Person'> <class '__main__.Person'>
True
False
False
False 1861692688688 1861692688976 <class 'str'> <class 'str'>
True 1861692688688
True 1861692688688
True 1861692688688
False 1861692463456 1861631148624 1861692462304 1861631148624 <class '__main__.Birthday'> <class 'int'>
True 1861692463456 1861631148624
True 1861692463456 1861631148624
False 1861692460864 1861631148624
1861631148336 1861631148336

1.6.with上下文管理器

from contextlib import contextmanager, closing


def m1():
    """覆写的方式打开文件,写入后需要关闭,如果中途发生异常,导致文件句柄无法被释放,资源泄露"""
    f = open('output.txt', 'w')
    f.write('hello ,世界')
    f.close()


def m2():
    f = open('output1.txt', 'w')
    try:
        f.write('nihao ,shijie ')  # 万一写入错误,可以关闭文件,收回资源
    except IOError:
        print("error")
    finally:
        f.close()


def m3():
    """用with,自动关闭"""
    with open('output2.txt', 'w') as f:
        f.write('wodayi了,111')
# m1()
# m2()
# m3()


class File(object):
    """创建实例对象,有__enter__和__exit__方法就是一个上下文管理器(协议),可以用with"""

    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):  # 申请资源时执行,with语句块之前被调用
        print('entering')
        self.f = open(self.filename, self.mode)
        return self.f

    def __exit__(self, exc_type, exc_value, exc_tb):  # 分别为异常类型,对象,堆栈信息
        # 释放资源时执行,with语句块之后被调用,异常时__exit__返回异常信息
        print('will exit')
        print('exc_type: %s' % exc_type)
        print('exc_value: %s' % exc_value)
        print('exc_tb: %s' % exc_tb)
        self.f.close()
        if exc_type is not None:  # 如果 with 内有异常发生 抛出异常
            raise exc_type


# f = File()  # f指向的对象就是一个上下文管理器中__enter__返回的值,这里就是self.f
with File('out.txt', 'w') as f:
    print('writing', '1/0')  # 异常时__exit__返回异常信息
    f.write('自制上下文管理器')
print('----------生成器上下文管理器')


@contextmanager  # 导入包装饰器
def my_open(path, mode):
    """申请资源,释放资源"""
    f = open(path, mode)  # 发生异常将会中断执行
    yield f
    f.close()


with my_open('out2.txt', 'w') as f1:  # 前面执行函数,返回值f赋值给f1
    f1.write('生成器上下文管理器')  # 执行完后,自动到函数中执行yield下的,释放资源


@contextmanager
def test():
    print('before')
    try:
        yield 'hello'
        # 这里发生异常 必须自己处理异常逻辑 否则不会向下执行
        a = 1 / 0
    finally:
        print('after')
# with test() as t:
#     print(t)


class Test():
    """定义了 close 方法才可以使用 closing 装饰器"""

    def close(self):
        print('closed')


with closing(Test()):  # with块执行结束后,自动执行close方法,自定义关闭资源
    print('do something')
entering
writing 1/0
will exit
exc_type: None
exc_value: None
exc_tb: None
----------生成器上下文管理器
do something
closed

1.7.python内建函数map|filter|reduce

"""终端显示内建函数dir(__builtins__)
下面为高阶函数,参数为函数和可迭代对象(list,tuple等)"""

from collections.abc import Iterable, Iterator
from functools import reduce

# 1.range
print('---range---'*10)
a = range(10)  # 可迭代对象
print(isinstance(a, Iterable))  # 是否可迭代
print(isinstance(a, Iterator))  # 是否是迭代器
print(a, type(a))  # range(0, 10) <class 'range'>
# 2.map(function, iterable, ...)处理数据后返回,是一种映射函数,返回可迭代对象
print('---map---'*10)
a1 = map(lambda x: x * x, [1, 2, 3, 4])  # 可迭代对象,map是一种映射
print(a1)
for i in a1:
    print(i)

a2 = map(lambda x, y, z: x + y + z, [1, 2, 3], (4, 5, 6), (7, 8, 9))
for i2 in a2:
    print(i2)


def f1(x, y):
    return x, y


n = (1, 2, 3, 4)
m = ['a', 'b', 'c', 'd']
a3 = map(f1, n, m)
for i in a3:
    print(i)


# 3.filter(function, iterable)过滤函数,True留下<=>[ item for item in iterables if function(item)],得到子集
print('---filter---'*10)
a4 = filter(lambda x: x % 2, [1, 2, 3, 4, ])
print(a4)
print(list(a4))


def isodd(num):
    if num % 2 == 0:
        return True
    else:
        return False


print(list(filter(isodd, range(1, 13))))

# 4.reduce(function,sequence[,initial]=>value),有种递推的感觉,连续执行逻辑,reduce(f,[x1,x2,x3,x4,x5]) = f(f(f(x1,x2),x3),x4)
print('---reduce---'*10)
a5 = reduce(lambda x, y: x + y, [1, 2, 3, 4, ])  # 先把1,2给x,y,然后生成的结果给x,y依次取后面的数
a6 = reduce(lambda x, y: x + y, [1, 2, 3, 4], 100)  # 100初始化x,y依次取数
a7 = reduce(lambda x, y: x + y, ['a1', 'b1', 'c1'], 'd1')  # d1a1b1c1,注意顺序
print(a5)
print(a6)
print(a7)


def multi(x, y):  # 累乘
    return x*y


print(reduce(multi, [1, 2, 3, 4]))

# 5.sorted(iterable,  key=None, reverse=False),所有可迭代对象排序操作默认False生序
print('---sort---'*10)
a8 = [5, 7, 6, 3, 4, 1, 2]
a9 = sorted(a8)  # 保留原列表,深拷贝新建对象
print(a8, a9, id(a8), id(a9))
a8.sort()  # 更改原列表,id不变
print(a8, id(a8))
info = [('Apple', 800, 9799),  # brank,sell,price
        ('Xiaomi', 40, 3599),
        ('Oppo', 40, 4199),
        ('Vivo', 100, 4000),
        ('Huawei', 40, 6899),]
print(
    info,
    sorted(info, key=lambda x: (x[1], x[2]), reverse=True),  # 先销量,再价格排序,降序
    sorted(info, key=lambda x: x[2], reverse=True),  # 按价格
    sep='\n',
)
---range------range------range------range------range------range------range------range------range------range---
True
False
range(0, 10) <class 'range'>
---map------map------map------map------map------map------map------map------map------map---
<map object at 0x000001B175849A80>
1
4
9
16
12
15
18
(1, 'a')
(2, 'b')
(3, 'c')
(4, 'd')
---filter------filter------filter------filter------filter------filter------filter------filter------filter------filter---
<filter object at 0x000001B17584BEB0>
[1, 3]
[2, 4, 6, 8, 10, 12]
---reduce------reduce------reduce------reduce------reduce------reduce------reduce------reduce------reduce------reduce---
10
110
d1a1b1c1
24
---sort------sort------sort------sort------sort------sort------sort------sort------sort------sort---
[5, 7, 6, 3, 4, 1, 2] [1, 2, 3, 4, 5, 6, 7] 1861692828736 1861692951936
[1, 2, 3, 4, 5, 6, 7] 1861692828736
[('Apple', 800, 9799), ('Xiaomi', 40, 3599), ('Oppo', 40, 4199), ('Vivo', 100, 4000), ('Huawei', 40, 6899)]
[('Apple', 800, 9799), ('Vivo', 100, 4000), ('Huawei', 40, 6899), ('Oppo', 40, 4199), ('Xiaomi', 40, 3599)]
[('Apple', 800, 9799), ('Huawei', 40, 6899), ('Oppo', 40, 4199), ('Vivo', 100, 4000), ('Xiaomi', 40, 3599)]

1.8.python面向对象编程

1.8.1.认识感受对象继承

class CanWeb():
    """上网的功能"""

    def web(self):
        print('可以上网')


class Minios(object):
    '''Minios 操作系统类'''

    def __init__(self, name):
        self.name = name
        self.apps = []  # 已经安装的应用程序名称列表

    def __str__(self):  # 自动执行方法,输出信息
        return "%s 安装的软件列表为 %s" % (self.name, str(self.apps))

    def install_app(self, app):  # 安装APP的方法
        if app.name in self.apps:
            print("已经安装了%s,无需再安装" % app.name)
        else:
            app.install()
            self.apps.append(app.name)


class App(object):
    """docstring for App"""
    law = '符合规定'

    def __init__(self, name, version, desc):
        self.name = name
        self.version = version
        self.desc = desc

    def __str__(self):
        return "%s 的当前版本是%s--%s" % (self.name, self.version, self.desc)

    def install(self):
        print("将%s [%s] 的执行程序复制到程序目录...-----" % (self.name, self.version))


class PyCharm(App):
    """具体pycharm类"""
    pass


class Chrome(App, CanWeb):
    """chrome类"""
    # 多继承,从左到右继承,父类方法相同,优先左侧
    # 覆写
    law = '安全的'

    def install(self):
        print("正在解压缩安装程序...")
        # 子类中调用父类变量,或者方法
        # print(App.law)
        print(super().law)
        # App.install(self)
        super().install()


linux = Minios("Linux")
print(linux)
pycahrm = PyCharm("PyCharm", "1.0", "python开发的IDE环境")
chrome = Chrome("Chrome", "2.0", "谷歌浏览器")
chrome.web()  # 返回是否能上网
linux.install_app(pycahrm)
linux.install_app(chrome)
linux.install_app(chrome)
app = App('超级软件', '6.0', 'xxxxxx')
linux.install_app(app)
"""看似调用相同的方法,如果是父类创建的对象,直接调用父类的方法,
如果是子类的对象,如果子类从写父类方法,用子类方法,否则用父类方法"""
Linux 安装的软件列表为 []
可以上网
将PyCharm [1.0] 的执行程序复制到程序目录...-----
正在解压缩安装程序...
符合规定
将Chrome [2.0] 的执行程序复制到程序目录...-----
已经安装了Chrome,无需再安装
将超级软件 [6.0] 的执行程序复制到程序目录...-----





'看似调用相同的方法,如果是父类创建的对象,直接调用父类的方法,\n如果是子类的对象,如果子类从写父类方法,用子类方法,否则用父类方法'

1.8.2.认识类方法

class Foo(object):
    size = '不大'  # 类属性,只有一份

    def __new__(cls, *args, **kwargs):
        '''自动调用,创建对象,必须有cls参数,返回实例化对象'''
        print('调用__new__()方法')
        return super().__new__(cls)

    def __init__(self, name):
        '''自动调用,接收返回的实例化对象,初始化对象'''
        self.name = name  # 实例属性,每个实例都有

    def ord_func(self):
        '''定义一个实例方法,至少有一个self参数'''
        print('实例方法')

        @classmethod
        def class_func(cls):
            '''定义类方法,至少有一个cls参数,一般定义与类相关和具体对象无关的操作,
            类方法只能访问类变量,不能访问实例变量,实例对象和类都可以调用类方法'''
            print('类方法')

        @staticmethod
        def static_func():
            '''定义静态方法,无默认参数,一般作为工具方法使用,与类和对象无关,静态方法只能访问类的成员,不能访问属于对象的成员,
            对象名./类名. 都可以调用静态方法'''
            print('静态方法')


a = Foo('张三')
print(a.name, a.size, Foo.size)
'''__more__属性来查看类的搜索顺序'''
调用__new__()方法
张三 不大 不大





'__more__属性来查看类的搜索顺序'

1.8.3.魔术方法

class Student:
    # 内部定义属性,可以省略,直接在初始化方法中定义,也可以在类外面定义
    name = None
    age = None
    tel = None
    #__开头的为私有变量或私有方法,类对象不可访问,但是类内部可以访问
    __body = '身体健康'
    def __init__(self, name, age, tel):
        # 构造方法自动执行,外面传的参数可以直接使用,但是后面的方法使用类的变量,要用 self.变量
        # 类的方法必须带self
        self.name = name
        self.age = age
        self.tel = tel
        print('创建了一个对象')
    def __str__(self):
        # print(对象)输出内存地址,用了__str__返回说明
        return "Student类的说明"
    def __del__(self):
        # 当实例对象被删除时 ,del stu1,自动执行,或者程序执行完,对象被释放,自动执行
        print(f'{self.name}已经被删除')

    def __lt__(self, other):
        # 有了,可以比较两个对象的大小,只能用于小于和大于
        return self.age < other.age
    def __le__(self, other):
        # 有了,可以比较两个对象的<=,>=
        return self.age <= other.age

    def __eq__(self, other):
        # 有了可以比较两个对象的属性是否相等,否则比较内存地址
        return self.age == other.age
    def __eyes_ok(self):
        # 私有变量加上self
        print(f'眼睛没有问题,{self.__body}')
    def tijian(self):
        # 所有方法加上self
        self.__eyes_ok()
stu1 = Student('张三', 18, '19140978362')
stu2 = Student('张四', 12, '13232328362')
print(stu1.name)
# del stu1
print(stu1)
print(stu1 < stu2)
print(stu1 > stu2)
print(stu1 <= stu2)
print(stu1 >= stu2)
stu1.tijian()
创建了一个对象
创建了一个对象
张三
Student类的说明
False
True
False
True
眼睛没有问题,身体健康

1.8.4.联合类型注解

# 联合类型注解
from typing import Union
# 类型注解,帮助第三方IDE工具进行代码推断,协助代码提示,同时帮助开发者自己做类型注释,备注,错了没关系
# 1.变量的类型注解,两种方式
var1: int = 10
var2: list = [1, 2, 3]
var3: str = 'qwer'
var4: bool = False
class Student():
    pass

stu: Student = Student()
var21: list[int] = [1, 2, 3]
var31: str = 'qwer'
var41: bool = False
var51: dict[str, int] = {'a': 1, "b": 2}
var512: dict[str, Union[int, str]] = {'a': 1, "b": 'wer'}  # 联合类型注解
var61: tuple[str, int, bool] = ('ads', 23, False)
var511 = {'a': 1, "b": 2}  # type:dict[str, int]
var611 = ('ads', 23, False)  # type:tuple[str, int, bool]

def x():
    return 10
var711 = x()  # type:int
# 2.函数的类型注解,行参/返回值的类型注解
def add(x: Union[int, str, list], y: Union[int, str, list]) -> Union[int, str, list]:
    return x + y
print(add(1, 6))
7

1.8.5.多态

# 多态,同样的方法,输入不同的对象得到不同的结果,同一种行为,不同的运行状态
class AC():  # 抽象类,只实现顶层设计
    def cool_wind(self):
        '''制冷'''
        # 抽象方法
        pass

    def hot_wind(self):
        '''制热'''
        pass

    def swing_wind(self):
        '''摆风'''
        pass


class Midea_AC(AC):
    def cool_wind(self):
        '''制冷'''
        print('美的空调制冷')

    def hot_wind(self):
        '''制热'''
        print('美的空调制热')

    def swing_wind(self):
        '''摆风'''
        print('美的空调摆风')


class GREE_AC(AC):
    def cool_wind(self):
        '''制冷'''
        print('格力空调制冷')

    def hot_wind(self):
        '''制热'''
        print('格力空调制热')

    def swing_wind(self):
        '''摆风'''
        print('格力空调摆风')

# 配合多态完成:1.抽象的父类设计(设计标准),2.具体的子类实现(实现标准)


def make_cool(ac: AC):
    # 声明是父类对象,实际传入子类对象就可以
    ac.cool_wind()


midea_ac = Midea_AC()
gree_ac = GREE_AC()
make_cool(midea_ac)
make_cool(gree_ac)
美的空调制冷
格力空调制冷

1.8.6.设计模式

# 设计模式就是代码实现的套路
# 1.单例模式,创建一个工具类的对象,导入到其他工程文件中,复制引用,不占用大量内存
# 2.工厂模式,由源生类创建的对象,使用特定的工厂来创建
# 3.还有很多模式待探索
class Persion():
    pass


class Worker(Persion):
    print('worker is created')
    pass


class Student(Persion):
    """docstring for Student"""
    print('student is created')
    pass


class Teacher(Persion):
    print('tercher is created')
    pass


class PersonFactory():
    # 工厂类,有点,,得到对象的入口是统一的便于维护,对象类的构造方法发生了改变,不需要动太多代码,直接修改工厂类,更接近现实世界
    def get_person(self, p_type):
        if p_type == 'w':
            return Worker()
        elif p_type == 't':
            return Teacher()
        else:
            return Student()


pf = PersonFactory()
worker1 = pf.get_person('w')
teacher1 = pf.get_person('t')
student1 = pf.get_person('s')
worker is created
student is created
tercher is created

1.8.7.多线程编程

# 进程,线程,并行执行的理解
import time
import threading  # 多线程模块


def sing(msg):
    start_time = time.time()  # 注意死循环,加个5s保护
    print(start_time)
    while 1:
        print(f'{msg}在唱歌...啦啦啦')
        time.sleep(0.5)
        if time.time()-start_time > 5:
            # print(time.time()-start_time,time.time())
            break


def dance(msg):  # 注意死循环,加个5s保护
    start_time = time.time()
    print(start_time)
    while 1:
        print(f'{msg}在跳舞...咚咚咚')
        time.sleep(0.5)
        if time.time()-start_time > 5:
            # print(time.time()-start_time,time.time())
            break


if __name__ == '__main__':
    # sing()
    # dace()
    # 创建一个唱歌的线程
    sing_thread = threading.Thread(target=sing, args=('小明', ))  # args 元组传参
    # 创建一个跳舞的进程
    dance_thread = threading.Thread(
        target=dance, kwargs={'msg': '小黑子'})  # kwargs 字典传参
    # 开始执行
    sing_thread.start()
    dance_thread.start()
1701963690.3537943
小明在唱歌...啦啦啦
1701963690.3537943
小黑子在跳舞...咚咚咚
小明在唱歌...啦啦啦小黑子在跳舞...咚咚咚

小明在唱歌...啦啦啦小黑子在跳舞...咚咚咚

小黑子在跳舞...咚咚咚
小明在唱歌...啦啦啦
小黑子在跳舞...咚咚咚小明在唱歌...啦啦啦

小黑子在跳舞...咚咚咚小明在唱歌...啦啦啦

小明在唱歌...啦啦啦
小黑子在跳舞...咚咚咚
小明在唱歌...啦啦啦小黑子在跳舞...咚咚咚

小明在唱歌...啦啦啦小黑子在跳舞...咚咚咚

小明在唱歌...啦啦啦小黑子在跳舞...咚咚咚

1.9.递归

# 递归,函数内部调用自己
# 注意递归返回值的接收,递归的退出条件
import os


def test_os():
    print(os.listdir(r'E:\s\t'))  # 文件夹下的目录
    print(os.path.isdir(r'E:\s\t\a'))  # 判断是否是目录
    print(os.path.exists(r'E:\s\t\a'))  # 路径是否存在


def get_file(path):
    print(f'当前判断的文件夹是{path}')
    file_list: list = []
    if os.path.exists(path):
        for i in os.listdir(path):
            new_path = path + '\\' + i
            if os.path.isdir(new_path):
                # 递归关键
                file_list += get_file(new_path)
            else:
                file_list.append(new_path)
    else:
        print(f'你是输入的路径{path}不存在')
    return file_list


if __name__ == '__main__':
    print(get_file(r'E:\s\t\a'))
当前判断的文件夹是E:\s\t\a
你是输入的路径E:\s\t\a不存在
[]
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值