Python面向对象学习(二)

  • Post author:
  • Post category:python




动态给实例添加属性和方法



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 版权协议,转载请附上原文出处链接和本声明。