vs 生成get set_property_with_生成器_拷贝

d8eb4bcfc60889930e3d486f21b2acdf.png

1. property 属性

1.1 类属性方式实现

class Dog(object):
    def __init__(self, age):
        self.__age = age  # 私有属性,只能在当前类内部访问的属性, 定义,属性前加两个下划线

    def get_age(self):
        """定义方法,获取对象的 age 属性"""
        return self.__age

    def set_age(self, new_age):
        """定义方法,设置对象的 age 属性"""
        self.__age = new_age

    # 类属性方式实现 property 属性, 在类中, 方法外部定义的变量,就是类属性
    # 使用 python 自带的方法,定义类属性  property(获取属性的方法, 设置属性的方法)
    age = property(get_age, set_age)


if __name__ == '__main__':
    # 创建对象
    dog = Dog(2)
    # print(dog.get_age())
    # dog.set_age(3)
    # print(dog.get_age())
    # property 属性, 按照使用属性的方式, 调用类中的方法
    print(dog.age)  # 调用 get_age 方法
    dog.age = 4   # 调用 set_age 方法
    print(dog.age)

1.2 装饰器的方式实现

class Dog(object):
    def __init__(self, name, age):
        self. __name = name
        self.__age = age  # 私有属性,只能在当前类内部访问的属性, 定义,属性前加两个下划线

    def get_age(self):
        """定义方法,获取对象的 age 属性"""
        return self.__age

    def set_age(self, new_age):
        """定义方法,设置对象的 age 属性"""
        self.__age = new_age

    # 类属性方式实现 property 属性, 在类中,方法外部定义的变量,就是类属性
    # 使用 python 自带的方法,定义类属性  property(获取属性的方法, 设置属性的方法)
    age = property(get_age, set_age)

    # 使用装饰器的方式实现 property 属性
    @property
    def name(self):  # 这个方法等价于 get_name
        return self.__name

    @name.setter
    def name(self, new_name):  # 等价于 set_name 方法
        self.__name = new_name


if __name__ == '__main__':
    dog = Dog('大黄', "2")
    print(dog.name)
    dog.name = '小白'
    print(dog.name)

2. with 语句和上下文管理器

with open('a.txt', 'r')  as f:
    pass
使用 with 的好处: 不用关闭文件,会自动关闭,
原因: 上下文管理器对象存在
上下文管理器对象: 一个类如果实现了 __enter__  和 __exit__ 这两个魔法方法,这个类的对象就是上下文管理器对象
with 语法 , 先进入上文方法, 即 __enter__ 方法
当 with 缩进中的代码,执行结束, 会执行 __exit__ 下文方法,可以在下文方法中关闭文件

补充: 
pymysql.connect() 返回连接对象,使用结束后需要关闭连接 连接对象是上下文管理器,即可以使用 with
with pymysql.connect() as cursor:  # 使用 with connect 得到的游标对象
    pass
连接对象.cursor() 返回的是游标对象 可以使用 with
with 连接对象.cursor() as  cursor:
    pass
class File(object):
    def __init__(self, filename, mode):
        """filename 文件名字, mode 文件的打开权限"""
        self.filename = filename
        self.mode = mode
        print("__init__ 方法被调用")

    # 定义上文方法, 获取资源的,参数一般只有 self, 不需要别的
    # with 后的语句,对象创建出来之后,会自动执行这个方法
    # 即 __init__ 方法执行之后,会执行(前提是使用 with)
    def __enter__(self):
        print('__enter__ 方法被调用')
        # 获取文件对象, open 打开文件
        self.fp = open(self.filename, self.mode, encoding='utf-8')
        # 将这个文件对象进行返回
        return self.fp

    # 定义下文方法, 释放资源, 比如 关闭文件对象    __exit__ 方法
    # 执行下文方法的时机:1. with 语句的代码执行结束,  2. 当 with 语句中的代码发生异常,也会进入
    def __exit__(self, exc_type, exc_val, exc_tb):
        # exc_type  异常的类型, 如果没有异常, 是 none
        # exc_val  异常的值, 即异常额描述信息
        # exc_tb   Traceback 对象
        # 函数的返回值, True, 代表发生的异常在 __exit__ 方法中结束,不再想上传递
        # 函数的返回值, False, 代表异常会向外层传递
        print(f"exc_type {exc_type}")
        print(f"exc_val {exc_val}")
        print(f"exc_tb {exc_tb}")
        # 关闭文件
        self.fp.close()
        print("__exit__ 方法被调用")
        # 可以使用 三个参数判断是否发生异常,以及对异常进行处理
        if exc_type:
            # 发生异常
            print('发生异常')
            return True  # 拦截异常,使异常不再向外传递
        else:
            # 没有异常  None
            print('没有发生异常')

if __name__ == '__main__':
    with File('a.txt', 'w') as f:  # ① 先创建 File 类的对象, ② 执行上文方法
        # f.write('bbb')
        f.read()  # 使用 w 方式打开文件,只能写文件,不能读取,会发生异常
    # ③ with 语句结束之后,执行下文方法

3. 生成器

3.1 生成器推导式

"""
生成器推导式和列表推导式非常像,只是将 []  换成 ()
列表推导式: 直接生成所有的数据
生成器推导式: 不是一次全部生成数据,存储生成数据的方法, 使用一个数据,生成一个数据
好处: 节省内存
"""
# 列表推导式
my_list = [i for i in range(5)]
print(my_list)  # [0, 1, 2, 3, 4]

# 生成器, 保存的生成数据的规则
my_gen = (i for i in range(5))
print(my_gen)
# 获取生成器中的数据  next(生成器对象)
print(next(my_gen))  # 0
print(next(my_gen))  # 1
print(next(my_gen))  # 2
print(next(my_gen))  # 3
print(next(my_gen))  # 4
# print(next(my_gen))  # 此时,生成数据的规则,已经不满足, 会抛出异常, StopIteration  异常

print("*" * 20)
# 获取生成器的数据,一般使用 for 循环, python 内部已经捕获了 StopIteration 的异常
my_gen = (i for i in range(5))   # 为什么不直接使用上边的生成器, 因为上边已经将数据去完了,不满足生成数据的规则了
for i in my_gen:
    print(i)  # 会自动进行 next 操作

3.2 yield 生成器

# 在函数中,如果出现了 yield 关键字,这个函数就是生成器, 同时 yield 可以实现协程(多任务)
def func():
    print('func start....')
    # yield 类似 return, ① 会生成 100 这个数据,并且能够将 100 这个数据返回到调用的地方
    # ② 函数遇到 yield 会暂停执行, 等待代码下一次 next, 才会继续执行
    yield 100
    # 再次 next 之后,会继续执行
    print('func 继续执行')
    yield 200
    print('func end ...')
    # 后续没有代码, 结束了,再次 next() 会抛出异常

if __name__ == '__main__':
    # 创建生成器对象
    my_gen = func()  # 正常的函数,会直接执行函数的代码, 存在 yield,生成器, 不会执行函数
    print(my_gen)
    # print(next(my_gen))  # 100
    # print(next(my_gen))  # 200
    # print(next(my_gen))  #
    for i in my_gen:  # for python 已经实现了 next 操作, 和捕获异常
        print(i)

3.3 案例

# 斐波那契数列
# 0 1 1 2 3

def fibonacci(num):
    """生成多少个斐波那契数列"""
    a = 0  # 第一个数据是 0
    b = 1  # 第二个数据是 1
    current_index = 0  # 以及生成的数据个数
    while current_index < num:
        yield a  # 生成一个数据
        current_index += 1   # 生成数据的个数加 1
        #  改变 a 和 b 的值
        a, b = b, a+b

if __name__ == '__main__':
    # 创建对象
    fi = fibonacci(5)
    for i in fi:
        print(i)

4. 深拷贝和浅拷贝

拷贝: 将一个变量的值复制给另一个变量, 在这个过程中可能会开辟新的内存空间, 可能不会. 拷贝的意义: 拷贝能够保证原数据和拷贝之后的数据是一样的, 修改拷贝之后的数据, 可能不会影响原数据.

4.1 浅拷贝

# 不管浅拷贝还是深拷贝,都需要使用 系统的模块 copy
import copy
# 浅拷贝 copy.copy()  函数
# 1. 对于不可变类型来说,浅拷贝等同于引用,不会开辟新的空间
# 不可变类型  int  str  tuple
# 1.1 int
age = 18
age1 = copy.copy(age)
print(f"age: {age}, {id(age)}")
print(f"age1: {age1}, {id(age1)}")

# 1.2 str
my_str = 'hello'
my_str1 = copy.copy(my_str)
print(f"my_str : {my_str}, {id(my_str)}")
print(f"my_str1: {my_str1}, {id(my_str1)}")

# 1.3 tuple
my_tuple = (1, 2, [3, 4])
my_tuple1 = copy.copy(my_tuple)
print(f"my_tuple : {id(my_tuple)}, my_tuple[2]  {id(my_tuple[2])}")
print(f"my_tuple1: {id(my_tuple1)}, my_tuple1[2] {id(my_tuple1[2])}")

# 2. 对于可变类型, 只会对第一层对象开辟内存空间,(即 list 中嵌套一个 list,只会对最外层的 list 开辟空间)
# 可变类型: list set  dict
my_list = [1, 2, [3, 4]]
my_list1 = copy.copy(my_list)
print(f"my_list : {id(my_list)}, myList[2]  {id(my_list[2])}")
print(f"my_list1: {id(my_list1)}, myList1[2] {id(my_list1[2])}")

4.2 深拷贝

# 不管浅拷贝还是深拷贝,都需要使用 系统的模块 copy
import copy
# 深拷贝 copy.deepcopy() 函数
# 不可变类型  int  str  tuple
# 1.1 int  不会开辟新的空间
age = 18
age1 = copy.deepcopy(age)
print(f"age: {age}, {id(age)}")
print(f"age1: {age1}, {id(age1)}")

# 1.2 str  不会开辟新的空间
my_str = 'hello'
my_str1 = copy.deepcopy(my_str)
print(f"my_str : {my_str}, {id(my_str)}")
print(f"my_str1: {my_str1}, {id(my_str1)}")

# 1.3 tuple ① 如果元组的数据, 都是不可变类型, 没有可变类型, 不会开辟新的空间
# ② 如果元组中的数据包含可变类型,那就会对元组本身以及包含的可变类型开辟空间
my_tuple = (1, 2)
my_tuple1 = copy.deepcopy(my_tuple)
print(f"my_tuple  {id(my_tuple)}")
print(f"my_tuple1 {id(my_tuple1)}")
my_tuple = (1, 2, [3, 4])
my_tuple1 = copy.deepcopy(my_tuple)
print(f"my_tuple : {id(my_tuple)}, my_tuple[2]  {id(my_tuple[2])}")
print(f"my_tuple1: {id(my_tuple1)}, my_tuple1[2] {id(my_tuple1[2])}")

# 2. 对于可变类型, 会对所有的可变类型开辟空间
my_list = [1, 2, [3, 4]]
my_list1 = copy.deepcopy(my_list)
print(f"my_list : {id(my_list)}, myList[2]  {id(my_list[2])}")
print(f"my_list1: {id(my_list1)}, myList1[2] {id(my_list1[2])}")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值