python高级属性

1.迭代器和生成器

1.1可迭代对象的判断

使用for循环遍历取值的对象叫做可迭代对象

# 元组,列表,字典,字符串,集合,range都是可迭代对象
from collections import Iterable

# 判断对象是否是指定类型
result = isinstance((3, 5), Iterable)
print("元组是否是可迭代对象:", result)

result = isinstance([3, 5], Iterable)
print("列表是否是可迭代对象:", result)

result = isinstance({"name": "张三"}, Iterable)
print("字典是否是可迭代对象:", result)

result = isinstance("hello", Iterable)
print("字符串是否是可迭代对象:", result)

result = isinstance({3, 5}, Iterable)
print("集合是否是可迭代对象:", result)

result = isinstance(range(5), Iterable)
print("range是否是可迭代对象:", result)

result = isinstance(5, Iterable)
print("整数是否是可迭代对象:", result)

1.2 自定义可迭代对象

自定义可迭代对象: 在类里面定义__iter__方法创建的对象就是可迭代对象。

from collections import Iterable

# 自定义可迭代对象: 在类里面定义__iter__方法创建的对象就是可迭代对象
class MyList(object):

    def __init__(self):
        self.my_list = list()

    # 添加指定元素
    def append_item(self, item):
        self.my_list.append(item)

    def __iter__(self):
        # 可迭代对象的本质:遍历可迭代对象的时候其实获取的是可迭代对象的迭代器, 然后通过迭代器获取对象中的数据
        pass

my_list = MyList()
my_list.append_item(1)
my_list.append_item(2)
result = isinstance(my_list, Iterable)

print(result)

1.3 自定义迭代器对象

自定义迭代器对象: 在类里面定义__iter__和__next__方法创建的对象就是迭代器对象

iter函数: 获取可迭代对象的迭代器,会调用可迭代对象身上的__iter__方法
next函数: 获取迭代器中下一个值,会调用迭代器对象身上的__next__方法

from collections import Iterable

# 自定义可迭代对象: 在类里面定义__iter__方法创建的对象就是可迭代对象
class MyList(object):

    def __init__(self):
        self.my_list = list()

    # 添加指定元素
    def append_item(self, item):
        self.my_list.append(item)

    def __iter__(self):
        # 可迭代对象的本质:遍历可迭代对象的时候其实获取的是可迭代对象的迭代器, 然后通过迭代器获取对象中的数据
        my_iterator = MyIterator(self.my_list)
        return my_iterator


# 自定义迭代器对象: 在类里面定义__iter__和__next__方法创建的对象就是迭代器对象
class MyIterator(object):

    def __init__(self, my_list):
        self.my_list = my_list

        # 记录当前获取数据的下标
        self.current_index = 0

        # 判断当前对象是否是迭代器
        result = isinstance(self, Iterator)
        print("MyIterator创建的对象是否是迭代器:", result)

    def __iter__(self):
        return self

    # 获取迭代器中下一个值
    def __next__(self):
        if self.current_index < len(self.my_list):
            self.current_index += 1
            return self.my_list[self.current_index - 1]
        else:
            # 数据取完了,需要抛出一个停止迭代的异常
            raise StopIteration


my_list = MyList()
my_list.append_item(1)
my_list.append_item(2)
result = isinstance(my_list, Iterable)
print(result)

for value in my_list:
    print(value)

1.4 生成器的概念

生成器是一类特殊的迭代器,它不需要再像上面的类一样写__iter__()和__next__()方法了, 使用更加方便。

创建生成器方法一,只要把一个列表生成式的 [ ] 改成 ( )

my_list = [i * 2 for i in range(5)]
print(my_list)

# 创建生成器
my_generator = (i * 2 for i in range(5))
print(my_generator)

# next获取生成器下一个值
# value = next(my_generator)
#
# print(value)
for value in my_generator:
    print(value)

创建生成器方法二,在def函数里面看到有yield关键字那么就是生成器

def fibonacci(num):
    a = 0
    b = 1
    # 记录生成fibonacci数字的下标
    current_index = 0
    print("--11---")
    while current_index < num:
        result = a
        a, b = b, a + b
        current_index += 1
        print("--22---")
        # 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
        yield result
        print("--33---")
        return "嘻嘻"

fib = fibonacci(5)
value = next(fib)
print(value)

# return 和 yield的区别
# yield: 每次启动生成器都会返回一个值,多次启动可以返回多个值,也就是yield可以返回多个值
# return: 只能返回一次值,代码执行到return语句就停止迭代

2闭包和装饰器

2.1 闭包

外层函数返回内层函数的引用

# 定义一个函数
def test(number):
    def test_in(number_in):
        print("in test_in 函数, number_in is %d" % number_in)
        return number+number_in
    # 其实这里返回的就是闭包的结果
    return test_in


# 给test函数赋值,这个20就是给参数number
ret = test(20)

# 注意这里的100其实给参数number_in
print(ret(100))
#注 意这里的200其实给参数number_in
print(ret(200))

2.2 装饰器

是给函数添加额外的功能

# ##################无参,无返回##################################
# 装饰器作用在不改变原函数代码的情况下添加<<额外的功能>>
# 装饰前的test(就是原先定义的那个test函数),是由func指向
# 装饰后的test,其实调用的是call_fun


# 1.闭包
# 2.装饰器

# 1.闭包
def deco(func):
	def warpper():
		print("添加额外的功能")
 		func()

 	return warpper

 @deco
 def test():
 	print("test")

 test()
 
########################2.无参,有返回###################################
# 1.闭包
def deco(func):
 	def warpper():
 		print("添加功能")
 		return func()  # 返回原先函数的值

 	return warpper

# 2.装饰器
 @deco  # @deco ===> test = deco(test)
 def test():
 	print("test")
 	return 1000

 print(test())  # warpper

######################3.有参,无返回#####################
# 1.闭包
def deco(func):
	def warpper(args):
		print("添加功能")
 		func(args)  # 调用test

	return warpper


# 2.装饰器
@deco
def test(args):
	print(args)

 test(123)  # call_fun

######################4.有参,有返回############################

# 1.闭包
 def deco(func):
 	def warpper(args):
 		print("添加功能")
 		return func(args)

	return warpper

# 2.装饰器
 @deco
 def test(args):
 	return args

 print(test(1000))  # call_fun

####################5.不定长参数,返回###################################

# 1.闭包
def deco(func):
	def warpper(*args, **kwargs):
		print("call_funn", args)
		print("call_fun", kwargs)
		return func(*args, **kwargs)  # 拆包

	return warpper


# 2.装饰器
@deco
def test(*args, **kwargs):
	print(args)
	print(kwargs)
	return 100


print(test(1, a=2))  # 调用warpper

def deco1(func1):
   def warpper1(*args, **kwargs):
      print("添加功能--1")
      return func1(*args, **kwargs)

   return warpper1


def deco2(func2):
   def warpper2(*args, **kwargs):
      print("添加功能--2")
      return func2(*args, **kwargs)

   return warpper2


@deco2  test = deco2(warpper1)
@deco1  warpper1 = deco1(test)
def test():
   print("功能test")
test()

添加功能--2
添加功能--1
功能test

类装饰器

# 使用类装饰器

class SetFun(object):
   def __init__(self, func):
      self.func = func  # 把传入的函数引用保存

   def __call__(self, *args, **kwargs):
      # 添加的功能
      print("添加的功能", self.value)

      # 把以前的功能执行一下
      self.func()

   @classmethod
   def set_value(cls, value):
      print(value)
      # return SetFun
      # 类属性
      cls.value = value
      return cls


# @SetFun.set_value("添加功能!")
# 第一步SetFun.set_value("添加功能!"),返回类引用
# 第二步@类引用===> @SetFun ===> test = SetFun(test)

@SetFun.set_value("添加功能!")
def test():
   print("test")


3.拷贝

3.1 浅拷贝

浅拷贝是对一个对象的顶层数据的拷贝

import copy 
<<< a = [11,22,33]
<<< b = copy.copy(a)
<<< id(a)
<<< 59275144
<<< id(b)
<<< 59525600
<<< a.append(44)
<<< a
<<< [11, 22, 33, 44]
<<< b
<<< [11, 22, 33]

<<< a = [11,22]
<<< b = [22,33]
<<< id(a)
<<< 58890680
<<< id(b)
<<< 53652634
<<< c = [a,b]
<<< d = copy.copy(c)
<<< id(c)
<<< 52390123
<<< id(d)
<<< 53590678
<<< a.append(44)
<<< c
<<< [[11,22,44],[22,33]]
<<< d
<<< [[11,22,44],[22,33]]
<<< id(d[0])
<<< 58890680
<<< id(d[1])
<<< 53652634

3.2 深拷贝

深拷贝是对于一个对象所有层次的拷贝(递归)

import copy 
<<< a = [11,22,33]
<<< b = copy.deepcopy(a)
<<< id(a)
<<< 59275144
<<< id(b)
<<< 59525600
<<< a.append(44)
<<< a
<<< [11, 22, 33, 44]
<<< b
<<< [11, 22, 33]

<<< a = [11,22]
<<< b = [22,33]
<<< id(a)
<<< 58890680
<<< id(b)
<<< 53652634
<<< c = [a,b]
<<< d = copy.deepcopy(c)
<<< id(c)
<<< 52390123
<<< id(d)
<<< 53590678
<<< a.append(44)
<<< c
<<< [[11,22,44],[22,33]]
<<< d
<<< [[11,22],[22,33]]
<<< id(d[0])
<<< 58634589
<<< id(d[1])
<<< 56523852

注意 :

  1. copy.copy对于可变类型,会进行浅拷贝
  2. copy.copy和copy.deepcopy对于不可变类型没有意义,全部等价于对象之间的赋值操作。
  3. copy.copy和copy.deepcopy对于一维的数据一样的。

4.property属性

一种用起来像是使用的实例属性一样的特殊属性,可以对应于某个方法。

# ############### 定义 ###############
class Foo:
    def func(self):
        pass

    # 定义property属性
    @property
    def prop(self):
        pass

# ############### 调用 ###############
foo_obj = Foo()
foo_obj.func()  # 调用实例方法
foo_obj.prop  # 调用property属性
#coding=utf-8
# ############### 定义 ###############
class Goods:
    """python3中默认继承object类
        以python2、3执行此程序的结果不同,因为只有在python3中才有@xxx.setter  @xxx.deleter
    """
    @property
    def price(self):
        print('@property')

    @price.setter
    def price(self, value):
        print('@price.setter')

    @price.deleter
    def price(self):
        print('@price.deleter')

# ############### 调用 ###############
obj = Goods()
obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
del obj.price      # 自动执行 @price.deleter 修饰的 price 方法

property对象的类属性

class Foo:
    def func(self):
        return "test"

    BAR = property(func)

obj = Foo()
reuslt = obj.BAR  # 自动调用get_bar方法,并获取方法的返回值
print(reuslt)
property方法中有个四个参数 
第一个参数是方法名,调用 对象.属性 时自动触发执行方法
第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
#coding=utf-8
class Foo(object):
    def get_price(self):
        print("getter...")
        return '100'

    def set_price(self, value): 
        """必须两个参数"""
        print("setter...")
        return 'set value' + value

    def del_price(self):
        print("deleter...")
        return '100'

    BAR = property(get_price, set_price, del_price, "description...")

obj = Foo()

obj.BAR  # 自动调用第一个参数中定义的方法:get_price
obj.BAR = "200"  # 自动调用第二个参数中定义的方法:set_price方法,并将“200”当作参数传入
desc = Foo.BAR.__doc__  # 自动获取第四个参数中设置的值:description...
print(desc)
del obj.BAR  # 自动调用第三个参数中定义的方法:del_bar方法

5.魔法属性

5.1 doc

表示类的描述信息
在这里插入代码片

class Foo:
    """ 描述类信息,这是用于看片的神奇 """
    def func(self):
        pass

print(Foo.__doc__)
#输出:类的描述信息

5.2 module 和 class

  • module 表示当前操作的对象在那个模块
  • class 表示当前操作的对象的类是什么
# -*- coding:utf-8 -*-
--- test.py ---
class Person(object):
    def __init__(self):
        self.name = 'laowang'

--- main.py ---
from test import Person

obj = Person()
print(obj.__module__)  # 输出 test 即:输出模块
print(obj.__class__)  # 输出 test.Person 即:输出类

5.3 init

初始化方法,通过类创建对象时,自动触发执行

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


obj = Person('zhangsan')  # 自动执行类中的 __init__ 方法

5.4 del

当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,del的调用是由解释器在进行垃圾回收时自动触发执行的。

class Foo:
    def __del__(self):
        pass

5.5 call

  • 对象后面加括号,触发执行。
    注:init方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')


obj = Foo()  # 执行 __init__
obj()  # 执行 __call__

5.6 dict

  • 类或对象中的所有属性
    类的实例属性属于对象;类中的类属性和方法等属于类,即:
class Province(object):
    country = 'China'

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

    def func(self, *args, **kwargs):
        print('func')

# 获取类的属性,即:类属性、方法、
print(Province.__dict__)
# 输出:{'__dict__': <attribute '__dict__' of 'Province' objects>, '__module__': '__main__', 'country': 'China', '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Province' objects>, 'func': <function Province.func at 0x101897950>, '__init__': <function Province.__init__ at 0x1018978c8>}

obj1 = Province('山东', 10000)
print(obj1.__dict__)
# 获取 对象obj1 的属性
# 输出:{'count': 10000, 'name': '山东'}

obj2 = Province('山西', 20000)
print(obj2.__dict__)
# 获取 对象obj1 的属性
# 输出:{'count': 20000, 'name': '山西'}

5.7 str

  • 如果一个类中定义了str方法,那么在打印 对象 时,默认输出该方法的返回值。
class Foo:
    def __str__(self):
        return 'test'


obj = Foo()
print(obj)
# 输出:test

21.8 getitem、setitem、delitem

  • 用于索引操作,如字典。以上分别表示获取、设置、删除数据
# -*- coding:utf-8 -*-

class Foo(object):

    def __getitem__(self, key):
        print('__getitem__', key)

    def __setitem__(self, key, value):
        print('__setitem__', key, value)

    def __delitem__(self, key):
        print('__delitem__', key)


obj = Foo()

result = obj['k1']      # 自动触发执行 __getitem__
obj['k2'] = 'test'    # 自动触发执行 __setitem__
del obj['k1']           # 自动触发执行 __delitem__
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值