美文网首页
核心解密Python函数在(类与函数之间)和(类与类之间)互相调

核心解密Python函数在(类与函数之间)和(类与类之间)互相调

作者: KangSmit的算法那些事儿 | 来源:发表于2020-06-26 12:58 被阅读0次
    image.png

    一、类与函数之间

    首先来看一个函数间的调用

    类方法:

    #实现类中函数之间互相调用
    #下面一个学生的简单自我介绍为例子
    __metaclass__=type #自由的、动态的修改/增加/删除 类的或者实例中的方法或者属性
    class Stu:
        #指定类要处理的参数
        name=None #先设定为空,下面会传入
        age=None
        major=None
        school="哈尔滨工业大学"#类变量,被所有学生实例共有的属性或者特征
        def __init__(self,name,age,major): #构造名字与年龄的init方法
            self.name=name
            self.age=age
            self.major = major
        def Name_Age(self): #构造姓名与年龄的函数,分别传入self对应的年龄与姓名参数
            print("我叫" + self.name+ "," + "今年" + str(self.age) + "岁," + "主修专业" + self.major + "。") #遇到(,。文字等)都加“ ”
        def School(self): #再构造一个函数来说明学生的学校信息,可提前设定好,或者重新构造一个
            print("来自",Stu.school)
        def Total(self): #最后构造一个函数来互相调用上面的两个函数Name_Age和School
            Stu.Name_Age(self)
            Stu.School(self)
    #######################################################
    #先整体传入参数
    stu=Stu("马小云",20,"空气动力学") #传入姓名与年龄
    #############################################
    #(原始的调用方法)实例化对象进行调用
    print("***********************各自函数调用的方法********************************")
    stu.Name_Age() #调用指定函数
    stu.School() #再调用其他函数
    #############################################
    #(函数之间互相调用之后的方法)使用类中函数调用其他函数
    print("***********************类中方法互相调用函数********************************")
    stu.Total()  #导出结果
    #######################################################
    
    

    执行结果:


    image.png

    备注:

    (一)metaclass的作用是什么?

    metaclass能有什么用处,先来个感性的认识:

    1. 你可以自由的、动态的修改/增加/删除 类的或者实例中的方法或者属性

    2. 批量的对某些方法使用decorator,而不需要每次都在方法的上面加入@decorator_func

    3. 当引入第三方库的时候,如果该库某些类需要patch的时候可以用metaclass

    4. 可以用于序列化(参见yaml这个库的实现,我没怎么仔细看)

    5. 提供接口注册,接口格式检查等

    6. 自动委托(auto delegate)

    7. more...

    (二)metaclass的相关知识

    1. what is metaclass?

    1.1 在wiki上面,metaclass是这样定义的:In object-oriented programming,

    a metaclass is a class whose instances are classes.

    Just as an ordinary class defines the behavior of certain objects,

    a metaclass defines the behavior of certain classes and their instances.

    也就是说metaclass的实例化结果是类,而class实例化的结果是instance。我是这么理解的:

    metaclass是类似创建类的模板,所有的类都是通过他来create的(调用new),这使得你可以自由的控制

    创建类的那个过程,实现你所需要的功能。

    (三)metaclass基础

    • 一般情况下, 如果你要用类来实现metaclass的话,该类需要继承于type,而且通常会重写type的new方法来控制创建过程。

    当然你也可以用函数的方式(下文会讲)

    • 在metaclass里面定义的方法会成为类的方法,可以直接通过类名来调用

    (四)如何使用metaclass

    4.1 用类的形式

    4.1.1 类继承于type, 例如: class Meta(type):pass

    4.1.2 将需要使用metaclass来构建class的类的metaclass属性(不需要显示声明,直接有的了)赋值为Meta(继承于type的类)

    4.2 用函数的形式

    4.2.1 构建一个函数,例如叫metaclass_new, 需要3个参数:name, bases, attrs,

    name: 类的名字

    bases: 基类,通常是tuple类型

    attrs: dict类型,就是类的属性或者函数

    4.2.2 将需要使用metaclass来构建class的类的metaclass属性(不需要显示声明,直接有的了)赋值为函数metaclas_new

    (五) metaclass 原理

    5.1 basic

    metaclass的原理其实是这样的:当定义好类之后,创建类的时候其实是调用了type的new方法为这个类分配内存空间,创建

    好了之后再调用type的init方法初始化(做一些赋值等)。所以metaclass的所有magic其实就在于这个new方法里面了。

    说说这个方法:new(cls, name, bases, attrs)

    cls: 将要创建的类,类似与self,但是self指向的是instance,而这里cls指向的是class

    name: 类的名字,也就是我们通常用类名.name获取的。

    bases: 基类

    attrs: 属性的dict。dict的内容可以是变量(类属性),也可以是函数(类方法)。

    所以在创建类的过程,我们可以在这个函数里面修改name,bases,attrs的值来自由的达到我们的功能。这里常用的配合方法是

    getattr和setattr(just an advice)

    二、类与类之间调用函数

    下面实现python中在一个类中调用另一个类的函数方法

    #实现类与类中的函数调用
    class Person: #构造第一个类
        def __init__(self,name): #先定义init方法,指定参数
            self.name = name
        def go_to(self,position,type): #构造的函数
            '''
            :param position:地名参数
            :param type:去的方法
            :return:
            '''
            print('去:' + position)
            #此处调用另一个类:Car类的方法
            type.run()
    class Car: #构造第二个类
        def run(self):
            print('走你~')
    
    call = Person('小王')
    #为了让小王调用Car类中的run()方法,需实例化出一辆车
    toll = Car()
    #通过将Car类的对象toll传给call这个对象,从而达到调用toll方法run()的目的
    call.go_to('上海',toll)
    

    或者下面来一个号理解的例子

    #实现调用类与类之间的函数方法
    import numpy as np
    class Calculate(object): #构造第一个类
        def add(self, a, b): #构造加法函数
            a1 = np.add(a,  b)
            return a1
        def multiply(self,a, b):#构造乘法函数
            a2= np.multiply(a, b)
            return a2
        def reduce(self,a,b):#构造减法函数
            a3 = np.subtract(a, b)
            return a3
        def division(self,a, b):#构造除法函数
            a4 = np.divide(a, b)
            return a4
    class Total_grade(object):#构造第二个类
        def __init__(self): #构建一个init方法
            self.Calculate = Calculate() #该方法调用第一个类的方法
        def get_id(self,id): #身份证号或者什么号都行
            return id
    
        def get_name(self, grade):#名称参数
            return grade
    
        def get_totalgrade(self, c, d):#调用第二类方法 下面调用第一类方法
            return self.Calculate.add(c, d)#加法或者其他
    
    
    s = Total_grade()
    print(s.get_id('1234567890'))
    print(s.get_name('张飞'))
    print(s.get_totalgrade(2019,2020))
    

    执行结果:


    image.png

    三、嵌套类之间的函数调用

    1、内部与外部的类的调用

    先来介绍内部类与外部类是什么?
    看源码解析:

    #先来实现一个简单的init嵌套类的交互方法
    class MyOuter:#构造外部类
        age=19 #定义一个参数,这里暂时用不上,只是想说明类开始也可传入恒定参数
        def __init__(self,name):#构造一个init函数
            self.name=name
    
        class MyInner: #构造内部法类
            def __init__(self,inner_name): #类似的构造一个init函数
                self.inner_name=inner_name
    
    ###########################################################################
    out=MyOuter('王小二在门外(外部类)') #实例化调用外部的类
    #####################################
    #直接实例化内部类调用
    inner=out.MyInner('王小二在房间里inner(内部类)') #在从外部进入内部的类的函数
    print(inner.inner_name) #将实例中的参数传入:王小二在房间里inner(内部类)=inner_name
    ##########################################################################
    #直接实例化外部类调用
    out2=MyOuter #外部类参数
    print(out2.age) #调用外部类方法
    
    

    2、嵌套类之间的互相调用

    内部类调用外部类的类属性和类方法

    #实现内部类调用外部类的类属性和类方法:这里是类属性和类方法
    class MyOuter:
        age=19
        def __init__(self,name):
            self.name=name
            '''
            :#描述:classmethod 修饰符对应的函数不需要实例化,
            :不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,
            :可以来调用类的属性,类的方法,实例化对象等。
            '''
        @classmethod
        def outer_class_method(cls):
            print('我是外部类的类方法')
    
        class MyInner:
            def __init__(self,inner_name):
                self.inner_name=inner_name
            def inner_method(self):
                print('我是内部类的对象方法')
                MyOuter.outer_class_method()
    
    out=MyOuter('在门外')
    inner=out.MyInner('在屋里inner')
    inner.inner_method() #执行调用内部函数
    

    3、内部类调用外部对象的对象属性和方法

    class MyOuter:
        age=24
        def __init__(self,name):
            self.name=name
        @classmethod
        def outer_class_method(cls):
            print('我是外部类的类方法')
        def outer_obj_method(self):
            print('我是外部类对象的绑定方法')
    
        class MyInner:
            def __init__(self,inner_name,obj):
                self.inner_name=inner_name
                self.obj=obj
            def inner_method(self):
                print('我是内部类的对象方法')
                MyOuter.outer_class_method()
                self.obj.outer_obj_method()
    
    out=MyOuter('外部类')
    inner=out.MyInner('从外部类进入内部类inner',out)
    inner.inner_method() #调用方法
    

    参考文献

    参考文献1
    参考文献2
    参考文献3

    相关文章

      网友评论

          本文标题:核心解密Python函数在(类与函数之间)和(类与类之间)互相调

          本文链接:https://www.haomeiwen.com/subject/xqnyfktx.html