• python高级编程——入门语法(一)


    元类

      在python中一切皆对象,类也是对象,只不过类是一个创建对象的对象,我们可以在类中动态的创建一个类,比如

    def func(name):
        if name == "Plane":
            class Plane(object):
                pass
            return Plane
         else:
            class Metrorolite(object):
                pass
            return Mrtroolite

      虽然根据上述代码可以动态创建一个类,但是整个类的代码仍需要我们编写的

      type()有两种作用:

        1、检查对象类型

    class People(object):
        def __init__(self, id, name, employees):
            self.id = id
            self.name = name
        
        def func(self):
            return
    
    if __name__ == "__main__":
        id = 1001
        name = "abc"
        employees = [1,2,3]
        people = People(id, name, employees)
        # 检查整型
        print(type(id))   # <class 'int'>
        # 检查字符串型
        print(type(name))   # <class 'str'>
        # 检查列表型
        print(type(employees))  # <class 'list'>
        # 检查类的对象型
        print(type(people))    #  <class '__main__.People'>
        # 检查类类型
        print(type(People))    # <class 'type'>
        # 检查函数型
        print(type(people.func))   #   <class 'method'>
    
    # 如果我们对其结果再次type()得到的结果都是type类型,这就验证了一切解释对象

      2、还有一个高大上的作用就是动态的创建类

          语法:type(类名, 由父类名称组成的元组(可以为空), 包含属性的字典(名称和值))

          返回值是一个类

    # 空类
    Chinese = type("People", (), {})
    
    # 继承父类,父类以元组的形式表达
    Chinses = type("People", (object, ), {})
    
    # 给类一些属性(下述都是类属性)和方法(方法可以自定义,依次是实例方法、类方法、静态方法)
    
    def sayHI(self):
        print("HI")
    
    @classmethod
    def sayHello(cls):
        print("Hello")
    
    @staticmethod
    def sayBye():
        print("Bye")
    
    Chinese = type("People", (object, ), {"id": 1001, "name": "zhangsan", "func1": sayHI, "func2": sayHello, "func3": sayBye})
    
    # Chinese 不是类名,People是类名,Chinese是一个引用变量

      元类的定义:

        元类就是用来创建类的“东西” 

        元类是类的类, 是类的模板

        元类是用来控制如何创建类的, 正如类是创建对象的模板一样,而元类的主要目的是为了控制类的创建行为 

        元类的实例化结果是我们用class定义的类,正如类的实例为对象 

        type是python的一个内建元类, 用来直接控制生成类 

        python中任何class定义的类其实都是type类实例化的对象 

        当然了,你也可以创建自己的元类,需要继承 type。

      元类的定义和使用:

        通过函数返回一个元类:

    # 自定义函数
    def summary(a, b):
        return a+b
    
    
    # 这个函数的作用是修改当前类的属性的值和方法的功能,并且返回一个类
    def upper_attr(future_class_name, future_class_parent, future_class_attr):
    
        # 可以修改当前类定义的属性的值和方法的功能
        newAttr = {}
        for name, value in future_class_attr.items():
            if name == "bar":
                newAttr[name] = "变量值修改了"
            if name == "func":
                newAttr[name] = summary
    
        return type(future_class_name, future_class_parent, newAttr)
    
    
    class Operation(object, metaclass=upper_attr):
        bar = "修改之前的值"
        func = None
    
    
    if __name__ == "__main__":
        print(Operation.bar)    # 变量值修改了
        print(Operation.func(2, 4))    # 返回值6

        通过继承type生成元类(博主也没有看懂,了解即可,用到极少):

    class Meta(type):
        def __init__(cls, *args, **kwargs):
            super().__init__(*args)
    
        def __new__(cls, *args, **kwargs):
        name, bases, attrs = args
        return super().__new__(cls, name, bases, attrs)
    class M_Class(metaclass=Meta):
      def __new__(cls, *args, **kwargs):
        return super().__new__(cls)
      def __init__(self):
        pass

    动态语言

      静态语言和动态语言的区别:

    静态语言(强类型语言)
      静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要 求在使用变量之前必须声明数据类型。

      例如:C++、Java、Delphi、C#等。

    动态语言(弱类型语言)
      动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明, 通常变量的类型是被赋值的那个值的类型。

       例如:PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。

      动态语言的特性:

        运行的过程中给对象绑定(添加)属性

        运行的过程中给类绑定(添加)属性

        运行的过程中给类绑定(添加)方法

        运行的过程中删除属性、方法

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    def show():
        print("通过类动态增加类方法.")
    @classmethod
    def show2(cls):
        print("通过类动态增加类方法,并且打印id.", cls.id)
        
    if __name__ == "__main__":
        person = Person("张三", 22)
    
        # 运行过程中,给对象添加属性
        person.phone = "1847015XXXX"
        print(person.phone)       # 1847015XXXX
    
        # 运行过程中,对象是不能添加方法,否则会报错
        # person.func = show
        # person.func()
    
        # 运行过程中,给类增加属性
        Person.id = 10001
        print("对象访问类属性", person.id)  # 对象访问类属性10001
        print("类访问类属性", Person.id)    #  类访问类属性10001
        # 运行过程中给类增加方法
        Person.func = show
        Person.func()               #  通过类动态增加类方法.
        # 运行过程中给类增加类方法
        Person.func = show2
        Person.func()           #   通过类动态增加类方法,并且打印id。10001

    __slots__

      __slots__作用:

        Python允许在定义class的时候,定义一个特殊变量__slots__来限制该 class能添加的属性,当前类就不能定义或者增加__slots__之外的属性了

      __slots__注意事项:

        __slots__只对类的实例化对象进行限制,不对类进行限制,__slots__变量值是以元组形式表示

        __slots__不仅限制类对象的属性,还限制类对象的方法

        __slots__仅对当前类起作用,对继承的子类不起作用

        在子类中定义__slots__,子类允许定义的属性就是自身的__slots__加上父类的 __slots__

    class Person(object):
        __slots__ = ("name", "age")
        def __init__(self, name, age):
            self.name = name
            self.age = age
        
    if __name__ == "__main__":
        person = Person("张三", 22)
        # 运行过程中,给对象添加属性实例对象属性只限于name,age 
        # person.phone = "1847015XXXX"
        # print(person.phone)
        
        # 运行过程中,给类增加属性,__slots__ 不限制类
        Person.id = 10001
        print("对象访问类属性", person.id)  # 对象访问类属性 10001
        print("类访问类属性", Person.id)   # 类访问类属性 10001

    生成器

      概念:Python中,这种一边循环一边计算的机制,称为生成器:generator。

      创建生成器的两种方式:

         方法1:列表生成式的 [ ] 改成 ( )

          numbers = ( i for i in range(100))

          通过 next() 函数获得生成器的下一个返回值 

          没有更多的元素时,抛出 StopIteration 的异常 

          正确的方法是使用 for 循环,因为生成器也是可迭代对象,并且不需要关心 StopIteration 异

         方法2:使用函数创建生成器(实例)

    # 斐波那契数列
    def fibonacci(num):
        a = 0
        b = 1
        count = 0
        temp = 1
        while count < num:
            yield b
            a, b = b, a+b
            count += 1
    
    fi = fibonacci(4)
    print(next(fi))    # 1
    print(next(fi))    # 1
    print(next(fi))    # 2
    print(next(fi))    # 3
    
    # 没有更多的元素时,抛出 StopIteration 的异常
    # 正确的方法是使用 for 循环,因为生成器也是可迭代对象,并且不需要关心StopIteration 异常
    print(next(fi))    # error
    
    # 所以在使用生成器的时候,需要捕获异常
    fi = fibonacci(10)
    while True:
        try:
            print(next(fi))
        except StopIteration as e:
            print(e)
            break

        另外生成器也可以传递参数通过send(参数值):

    # 斐波那契数列
    def fibonacci(num):
        a = 0
        b = 1
        count = 0
        temp = 1
        while count < num:
            temp = yield temp*b
            print("temp{}:{}".format(count, temp))
            a, b = b, a+b
            count += 1
    fi = fibonacci(10)
    
    print(next(fi))
    while True:
        try:
            print(fi.send(1))
        except:
            break

    迭代器

      可迭代对象:   

        这里先提一下迭代器对象,如果一个对象可以通for循环进行遍历的对象一般都是迭代器对象;python提供了一个Iterable类就是鉴别对象是否是迭代器对象,在鉴别的过程中需要借助isinstance()方法,这个方法是鉴别对象是否属于一个类的对象,这里不能用type()方法,因为type()的作用是鉴别对象是否是类的实例化对象(通过继承的是false)

        首先先简单介绍两者检验对象类型的区别:

    class A:
        def __init__(self):
            pass
    
    class B(A):
        def __init__(self):
            super().__init__()
    
    if __name__ == "__main__":
        a = 123
        # 两者检验整型,类似这种,字符串、列表、元组、集合、字典都是一样的结果
        print(type(a) == int)     # True
        print(isinstance(a, int))    # True
        
        # 两者主要的区别 直接通过类生成的对象,两者检验的结果是一样的
        b = B()
        print(type(b) == B)    # True
        print(isinstance(b, B))    # True
        # 若是父类就会有不一样的结果
        print(type(b) == A)    # False
        print(isinstance(b, A))   # True

        所以在检验对象时,采用isinstance()比较好,

    from collections import Iterable
    
    class A:
        def __init__(self):
            pass
    
    class B(A):
        def __init__(self):
            super().__init__()
        
        # 实例生成器函数
        def func(self, a):
            yield a
            a = a + 1
            if a == 5:
                return
    
    if __name__ == "__main__":
        b = B()
        print(isinstance(b, Iterable))   #  False
        # 像集合数据类型都是可迭代对象,字符串、列表、元组、集合、字典
        b = ""
        print(isinstance(b, Iterable))   # True
        # 前面提到的生成器,他也是可迭代对象
        a = B()
        b = a.func(0)
        print(isinstance(b, Iterable))   # True

      迭代器:

        可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

        可以使用 isinstance() 判断一个对象是否是 Iterator 对象: 

        有两种情况是迭代器:

          1、通过生成器函数生成的生成器就是迭代器

          2、通iter()函数将可迭代对象转换成迭代器

    from collections import Iterator
    
    class A:
        def __init__(self):
            pass
    
    class B(A):
        def __init__(self):
            super().__init__()
        
        # 实例生成器函数
        def func(self, a):
            yield a
            a = a + 1
            if a == 5:
                return
    
    if __name__ == "__main__":
        b = B()
        print(isinstance(b, Iterator))   #  False
        # 像集合数据类型都是可迭代对象,字符串、列表、元组、集合、字典
        b = ""
        print(isinstance(b, Iterator))   # True
        # 前面提到的生成器,他也是可迭代对象
        a = B()
        b = a.func(0)
        print(isinstance(b, Iterator))   # True
        
        # 通过iter()函数将字符串、列表、元组、集合、字典转换成迭代器
        b = {}
        b = iter(b)
        print(isinstance(b, Iterator))

        迭代器是可以自定义,只要重写迭代器协议的两个方法    

          迭代器对象符合迭代器协议,提供两种方法: __iter__() 和 __next__()      

          __iter__ 返回迭代器对象,并在循环开始时隐式调用。 

           __next__方法返回下一个值,并在每个循环增量处隐式调用。    

           __next__在没有更多值返回时引发StopIteration异常,循环结构隐式捕获该 异常以停止迭代。 

    class Counter:
        def __init__(self, low, high):
            self.current = low
            self.high = high
        
        # 生成器的一般固定写法
        def __iter__(self):
            return self
        
        # 在下面函数可以改变迭代器返回的下一个值
        def __next__(self):
            if self.current > self.high:
                raise StopIteration
            else:
                self.current += 2
                return self.current -2
  • 相关阅读:
    前端知识点回顾之重点篇——ES6的async函数和module
    前端知识点回顾——Javascript篇(五)
    前端知识点回顾之重点篇——ES6的Iterator和Generator
    前端知识点回顾之重点篇——ES6的Promise对象
    前端知识点回顾——Javascript篇(四)
    前端知识点回顾之重点篇——JavaScript异步机制
    前端知识点回顾之重点篇——面向对象
    JS设计模式(9)享元模式
    JS设计模式(8)模板方法模式
    JS设计模式(7)组合模式
  • 原文地址:https://www.cnblogs.com/aitiknowledge/p/11447781.html
Copyright © 2020-2023  润新知