动态给实例添加属性和方法
MethodType
MethodType可以把外部函数(方法)绑定到类或类的实例中。(在python2和python3中MethodType的使用是有很大的不同的,有需要的可以自行查看一下)
slots
当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,当你需要限制可绑定的实例的属性的时候, 就可以使用__slots__
下面给出一些例子
from types import MethodType # 导入MethodType这个函数
class Cat(object): #创建一个猫类
__slots__ = ("run") # 允许在外部添加run这个方法
c = Cat() # 实例化对象
# self不能忘记,这是传入对象的参数
def run(self): # 在类的外部定义方法run
print("小猫在奔跑") # 打印这句换
c.run = MethodType(run,c) # 通过MethodType方法将run方法和对象c传入,绑定到实例对象上
c.run() #在这里通过实例对象调用run方法
结果:
from types import MethodType
class Person(object):
__slots__ = ("name","age","speak")
per = Person()
# 动态添加属性,这体现了动态语言的特点(灵活)
per.name = "bai"
print(per.name)
# 动态添加属性
# per.speak = say()
# per.speak()
def say(self):
print("my name is " + self.name)
per.speak = MethodType(say,per)
per.speak()
#如果想要限制实例的属性怎么办,比如只允许给对象添加name,age,height,weight属性
#在定义类的时候,定义一个特殊的属性(__slots__),可以限制动态添加属性、方法
结果:
property
定义
可以让受限制访问的属性使用点语法(“.”+属性名)
通过上面的代码可以了解到,有三种方式来访问我们类中的属性。
1、最简单的一种是,直接在类中声明出属性,然后通过“实例化对象.属性名”的方式来调用属性内容。但是这样属性直接对外暴露,是较为不安全的做法。这样就有了第二种
class Person(object):
def __init__(self,age):
# 属性直接对外暴露
self.age = age
per = Person(18)
print(per.age)
2、第二种是通过限制访问,这种方式需要我们编写该属性的get、set方法来获取和设置值。但这样的写法,是以调用方法的形式进行的,没有直接调用类的属性,给人一种不是很直观的感觉。
class Person(object):
def __init__(self,age):
#使用限制访问,需要自己写set和get方法才能够访问
self.__age = age
def getAge(self):
return self.__age
def setAge(self,age):
if age < 0:
age = 0
self.__age = age
per = Person(18)
#这样的写法,是以调用方法的形式进行的,没有直接调用类的属性,给人一种不是很直观的感觉
per.setAge(15)
print(per.getAge())
3、第三种则是采用property的方式来完成
class Person(object):
def __init__(self,age):
#使用限制访问,需要自己写set和get方法才能够访问
self.__age = age
方法名为受限制的变量去掉双下划线
@property #通过这个修饰,可以获取到相应的值,相当于getAge这个方法
def age(self):
return self.__age
@age.setter #去掉下划线。setter,相当于setAge这个方法
def age(self,age):
if age < 0:
age = 0
self.__age = age
#这种直接调用了,类里面的属性,然人看起来比较的直观
per.age = 100 #相当于调用setAge,这并不相当于添加了age属性,还是访问受限制的
print(per.age) #相当于调用getAge
结果:
运算符重载
常见运算符
add
定义:让自定义的类生成的对象(实例)能够使用运算符进行操作
str
定义:改变输出时候的格式
class Person(object):
def __init__(self,num):
self.num = num
# 运算符重载
def __add__(self,other): #self表示第一个对象,other表示第二个对象
return Person(self.num + other.num) # 返回一个对象,这里打印的话是一个地址
def __str__(self):
return "num = "+ str(self.num) # 通过重写str。可以将数值打印出来
per1 = Person(1)
per2 = Person(2)
print(per1 + per2) #per1 + per2 === per1.__add__(per2)
下面是重写cmp和pow的一段代码
class Student(object): #创建一个学生类
def __init__(self,grade): #重写学生类的构造方法,并添加了对象属性——成绩
self.grade = grade # 将传入的值和对象属性的值相等
def __pow__(self,other): # 重写运算符__pow__,并添加两个对象作为参数
a = pow(self.grade,2) # 将第一个对象中的成绩属性平方,然后赋值给变量a
b = pow(other.grade,2) # 将第二个对象中的成绩属性平方,然后赋值给变量b
print(a) # 打印出变量a
print(b) # 打印出变量b
def __cmp__(self, other): # 重写运算符__cmp__,并添加两个对象作为参数
if self.grade>other.grade: # 对第一个对象的成绩属性和第二个对象的成绩属性进行判断
print("学生1成绩更好!") #如果第一个对象的成绩大,则打印这句话
else:
print("学生2成绩更好!") #如果第二个对象的成绩大,则打印这句话
s1 = Student(95) # 实例化对象,并赋值属性成绩为95
s2 = Student(88) # 实例化对象,并赋值属性成绩为88
s1.__cmp__(s2) # 调用重写过后的运算符__cmp__并传入两个对象
s1.__pow__(s2) # 调用重写过后的运算符__pow__并传入两个对象
版权声明:本文为qq_52383774原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。