python笔记-进阶

目录

目录

参数传递

迭代器/生成器

比较

拷贝

进程VS线程VS协程

并发vs并行

装饰器

函数嵌套

函数装饰器

带参数的装饰器

带自定义参数的装饰器

类装饰器

枚举

上下文管理器



参数传递

Python 中参数的传递既不是值传递,也不是引用传递,而是赋值传递,或者是叫对象的引用传递

赋值或对象的引用传递,不是指向一个具体的内存地址,而是指向一个具体的对象

  • 如果对象是可变的,当其改变时,所有指向这个对象的变量都会改变。
  • 如果对象不可变,简单的赋值只能改变其中一个变量的值,其余变量则不受影响。

迭代器/生成器

迭代器生成器
说明

实现了__iter__和__next__方法的对象都称为迭代器

迭代协议:

当任何可迭代对象传入到for循环或其他迭代工具中进行遍历时,迭代工具都是先通过iter函数获得与可迭代对象对应的迭代器,然后再对迭代器调用next函数,不断的依次获取元素,并在捕捉到StopIteration异常时确定完成迭代

两种方式:

  • 普通函数使用了 yield 语句返回结果
  • 生成器表达式

对比
  • 迭代器和列表的区别:

列表一次性加载所有元素到内存中,而迭代器是以延迟计算的方式返回元素,等到调用next时才返回元素

  • 所有容器都是可迭代的,例如list、dict、tuple、set等

  • 列表推导式VS生成器表达式:

列表推导式一次性产生所有结果,而生成器表达式等到调用next时才返回元素

  • 生成器是一种特殊的迭代器
特点

  • 迭代器不可回退
  • 文件对象既是迭代器,又是可迭代对象
生成器只能遍历一次
优点
  • 减少内存
  • 提高代码可读性
举例
  • 将可迭代对象--->迭代器:(iter()函数)
L = [2,3,4]
I = iter(L)
  • 读取文件:(一次读一行)
f = open('myfile.txt')
print(next(f))
print(next(f))


-->
hello text file
goodbyt text file
  • 迭代器实现斐波那契数列:
class Fib:
    def __init__(self):
        self.prev = 0
        self.curr = 1

    def __iter__(self):
        return self

    def __next__(self):
        self.curr, self.prev = self.prev + self.curr, self.curr
        return self.curr

fib = Fib()
for i in range(10):
    print(next(fib))

  • 生成器表达式:(使用括号)
g = (x*2 for x in range(10))
  • 生成器实现斐波那契数列:
def fib():
    prev, curr = 0, 1
    while True:
        yield curr
        curr, prev = prev + curr, curr

f = fib()
for i in range(10):
    print(next(f))



 

比较

==is
说明比较对象之间的值是否相等
  • 比较的是对象的身份标识是否相等,即它们是否是同一个对象,是否指向同一个内存地址
  • 操作符'is'的速度效率,通常要优于'=='
其他出于对性能优化的考虑,Python 内部会对 -5 到 256 的整型维持一个数组,起到一个缓存的作用,所以这部分数据用is比较,结果为true

拷贝

赋值浅拷贝深拷贝
使用b=a
  • 切片操作:b = a[:]
  • 工厂函数:b = list(a)、b =set(a)...
  • copy 模块中的 copy 函数:b=a.copy()
b=copy.deepcopy(a)
说明
  • 对象的赋值即对象引用,他们指向同一片内存,b 不过是 a 的别名,是引用,它们的id是一样的
  • 值和地址都是一样的
  • 浅拷贝会创建新对象,其内容非原对象本身的引用,而是原对象内第一层对象的引用
  • 浅拷贝对于一维列表而言和深拷贝一样,而对于多维列表,修改B的一维内容时A不会变化;而修改高维内容时A也会随之变化
包含对象里面的子对象的拷贝,原始对象的改变不会造成深拷贝里任何子元素的改变
举例

import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
 
b = a                       #赋值,传对象的引用
c = copy.copy(a)            #对象拷贝,浅拷贝
d = copy.deepcopy(a)        #对象拷贝,深拷贝
 
a.append(5)                 #修改对象a
a[4].append('c')            #修改对象a中的['a', 'b']数组对象
 
print( 'a = ', a )
print( 'b = ', b )
print( 'c = ', c )
print( 'd = ', d )


# 输出结果
# ('a = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
# ('b = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
# ('c = ', [1, 2, 3, 4, ['a', 'b', 'c']])
# ('d = ', [1, 2, 3, 4, ['a', 'b']])

进程VS线程VS协程

说明特点
进程进程是一个实体,是一个具有独立功能的程序在某个数据集上的一次运行活动
  • 动态性:动态产生、动态消亡
  • 独立性:是系统分配资源和调度的基本单元
  • 并发性:可以和其他进程并发执行
线程线程是进程中的一个实体,是被系统独立调度和分派的基本单位
  • 同一进程中的多个线程并发执行,这些线程共享进程所拥有的资源
  • 进程是CPU资源分配的基本单位,线程是独立运行和独立调度的基本单位
  • 一个进程包含若干个线程线程的调度与切换比进程快很多
协程协程是一种比线程更加轻量级的存在,协程不被操作系统内核管理,协程是完全由程序控制的

协程不需要多线程的锁机制,因为只有一个线程,不存在变量冲突

并发vs并行

说明适用场景
并发同一时刻,只有一个线程/任务在执行,线程和任务相互切换进行适用io操作频繁的场景
并行多个进程同时进行适用cpu计算复杂的场景

如果是 I/O bound,并且 I/O 操作很慢,需要很多任务 / 线程协同实现,那么使用 Asyncio 更合适。

如果是 I/O bound,但是 I/O 操作很快,只需要有限数量的任务 / 线程,那么使用多线程就可以了。

如果是 CPU bound,则需要使用多进程来提高程序运行效率。

装饰器

函数嵌套

装饰器可以嵌套使用,执行顺序从里到外


@decorator1
@decorator2
@decorator3
def func():
    ...

执行顺序等价于:
decorator1(decorator2(decorator3(func)))

函数装饰器

带参数的装饰器


def decorator_a(func):
    def wrapper(message):
        print('wrapper of decorator')
        func(message)
    return wrapper


@decorator_a
def greet(message):
    print(message)


greet('hi')

# 输出
wrapper of decorator
hi

带自定义参数的装饰器


def repeat(num):
    def decorator_a(func):
        def wrapper(*args, **kwargs):
            for i in range(num):
                print('wrapper of decorator')
                func(*args, **kwargs)
        return wrapper
    return decorator_a


@repeat(4)
def greet(message):
    print(message)

greet('hello world')

# 输出:
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world

类装饰器

类装饰器主要依赖于函数__call__(),每当你调用一个类的示例时,函数__call__()就会被执行一次

eg:


class Count:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print('num of calls is: {}'.format(self.num_calls))
        return self.func(*args, **kwargs)

@Count
def example():
    print("hello world")

example()

# 输出
num of calls is: 1
hello world

example()

# 输出
num of calls is: 2
hello world

...

函数被装饰以后,它的元信息会改变,为了解决这个问题,我们使用内置的装饰器@functools.wrap,帮助保留原函数的元信息

eg:


import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('wrapper of decorator')
        func(*args, **kwargs)
    return wrapper
    
@my_decorator
def greet(message):
    print(message)

greet.__name__

# 输出
'greet'

枚举

定义:

from enum import Enum

@unique
class Role(Enum):
    father = 1
    mother = 2
    sister = 3
 

使用:


#调用枚举成员的 3 种方式
print(Role.father)
print(Role['father'])
print(Role(1))

-->
Role.father
Role.father
Role.father


#调取枚举成员中的 value 和 name
print(Role.father.value)
print(Role.father.name)

-->
1
father


#遍历枚举类中所有成员的 2 种方式
for role in Role:
    print(Role)

-->
Role.father
Role.mother
Role.sister

注意事项:

  • 枚举类中各个成员的值,不能在类的外部做任何修改
  • Python 枚举类中各个成员必须保证 name 互不相同,但 value 可以相同
  • 借助 @unique 装饰器,这样当枚举类中出现相同值的成员时,程序会报 ValueError 错误

上下文管理器

作用:防止资源泄露,释放系统资源,提高系统安全性

使用场景:文件的打开关闭、数据库的连接关闭、使用释放锁

用法:with 语句(有了with语句,就不用写关闭代码了)

打开文件

with open('test.txt', 'w') as f: 
    f.write('hello')

等同于


f = open('test.txt', 'w')
try:
    f.write('hello')
finally:
    f.close()

实现:

        基于类的上下文管理器:

用类来创建上下文管理器时,必须保证这个类包括方法”__enter__()”和方法“__exit__()”。其中,方法“__enter__()”返回需要被管理的资源,方法“__exit__()”里通常会存在一些释放、清理资源的操作


class FileManager:
    def __init__(self, name, mode):
        print('calling __init__ method')
        self.name = name
        self.mode = mode 
        self.file = None
        
    def __enter__(self):
        print('calling __enter__ method')
        self.file = open(self.name, self.mode)
        return self.file


    def __exit__(self, exc_type, exc_val, exc_tb):
        print('calling __exit__ method')
        if self.file:
            self.file.close()
            
with FileManager('test.txt', 'w') as f:
    print('ready to write to file')
    f.write('hello world')
    
## 输出
calling __init__ method
calling __enter__ method
ready to write to file
calling __exit__ method

        基于生成器的上下文管理器:

使用基于生成器的上下文管理器时,我们不再用定义“__enter__()”和“__exit__()”方法,但请务必加上装饰器 @contextmanager


from contextlib import contextmanager

@contextmanager
def file_manager(name, mode):
    try:
        f = open(name, mode)
        yield f
    finally:
        f.close()
        
with file_manager('test.txt', 'w') as f:
    f.write('hello world')

1、pipfile中引包,*表示任意版本的包,为防止兼容性问题,最好指定包版本,不用通配符

2、若pipfile文件中指定安装某插件报错,可尝试在jenkinsfile中强制安装

参考:https://blog.csdn.net/sinat_38682860/article/details/108681726?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.control

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值