美文网首页
核心解密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