Python 面向对象高级编程

面向对象高级编程

春花不红不如草,少年不美不如老。

限制实例的属性 slot

  • 使用__slots__这样不允许私自增加属性

class Student(obj):
    __slot__ = ('name','age') #使用元祖定义允许绑定的属性名称
  • 然后测试一下

s = Student()

s.name = 'Mike'

s.age = 18

s.score = 25

# 这样直接报错

由于 ‘score’ 没有放到slot中,所以不能绑定 score 属性,所以报错误

要注意的是 __slot__定义的属性仅仅对当前类的实例起作用,对继承的子类是不起作用的

  • 比如

class GraduateStudent():
      pass
 g = GraduateStudent()
 g.score = 9999

@property 装饰器负责把方法当成限制属性调用的

  • @property 属性

class Student(obj):

   @property
  def score(self):
    return self._score
   @score.setter
   def score(self,value):
     if not isinstance(value,int):
       raise ValueError('score must be an integer!')
     if value<0 or value>100:
       raise ValueError('score must be between 0 to 100 !')
     self._score = value

@property 的实现比较复杂,它是把一个 getter 方法变成属性,只需要加上@property 就可以了

@property 本身又创建了另外一个装饰器@score.setter 负责把一个 setter 方法变成属性在赋值.于是我们就拥有了一个可控的操作


s = Student()

s.score = 60 # OK 实际转化为s.set_score(60)

s.score  # OK 实际转化为s.get_score()

# 结果 60

s.score = 999

# 这样就报错误

  • @property 还可以定义只读属性,只定义 getter 方法,不定义 setter 方法就是个只读属性

class Student(obj):

    @property
    def birth(self):
        return self._birthday
    @birth.setter
     def birth(self,value):
       self._birth = value
    @property
      def age(self):
        return 2015 - self._birth

上面的 birth 就是可读写的 下面的 age 只能是可读的属性

@property 广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查

多重继承

  • 有的时候我们需要一个类继承好多个基类,用法类似

class Man():
    pass

class Woman():
    pass

class Person(Man,Woman):
   pass

通过多重继承一个子类就可以同时获取多个父类的所有功能

定制类

  • __str__ 返回一个用户看的懂的字符串,它必须和 print 结合使用

我们先定义了一个 Student 类,打印实例


 class Student():

     def __init__(self,value):
       self.name = name

     def __str__(self):
        return 'Student object(name:%s' %self.name)

print(Student('Mike'))
  • __call__ 一个对象实例可以又自己的属性和方法,当我们调用实例方法后,我们用 instance.method()来调用,自己掉自己

class Student():
     def __init__(self,name):
         self.name = name
     def __call__(self):
         print('My name is $s' % self.name)

# 调用方式
# s = Student('Mike')
# s()  # self参数不要传入
# My name is Mike

调用了 call 方法你完全可以把类当作一个方法,自己调自己

@classmethod 和@staticmethod 区别

  • 看代码

class test:

    class_name = "test"

    def __init__(self, name):
        self.class_name = name

    def my_print(self, value):
        print(value + " " +self.class_name)

    @staticmethod
    def my_static_print(val):
        print(val)

    @classmethod
    def my_class_print(cls, val):
        print(val +" "+ cls.class_name)


if __name__ == "__main__":
     my_test = test("xxx")

     test.my_static_print("static print")
     test.my_class_print("class print")
     my_test.my_static_print("static print")
     my_test.my_class_print("class print")
     my_test.my_print("my_print")
  • 最后结果

static print
class print test
static print
class print test
my_print xxx
  • 总结

classmathod 必须要传入一个 cls 参数,这个参数就代表类本身,后面跟的是值

staticmethod 则完全没必要

  • 记忆

如果你定义了一个方法它的返回值和类的属性以及实例无关,结果永远不变 那就用@staticmethod

如果你定义了一个方法它的返回值只和类的属性有关,结果可变.那就用@classmethod


文章作者: 雾烟云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 雾烟云 !
  目录