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() #导出结果
#######################################################
执行结果:
你可以自由的、动态的修改/增加/删除 类的或者实例中的方法或者属性
批量的对某些方法使用decorator,而不需要每次都在方法的上面加入@decorator_func
当引入第三方库的时候,如果该库某些类需要patch的时候可以用metaclass
可以用于序列化(参见yaml这个库的实现,我没怎么仔细看)
提供接口注册,接口格式检查等
自动委托(auto delegate)
more...
(二)metaclass的相关知识
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))
执行结果:
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() #调用方法