python day16 预置实例属性 、 类变量 、 静态方法 @staticmethod 、 运算符重载

目录:

预置实例属性 、 类变量 、 静态方法 @staticmethod 、 运算符重载

预置的实例属性:

dict属性:

用于绑定一个存储此实例自身变量的字典

class属性

用于绑定创建此实例的类

示例:

class Dog:
        pass
    dog1 = Dog()
    print(dog1.__dict__)
    dog1.color = "白色"
    print(dog1.__dict__)
    print(dog1.__class__)  

用于类型判断的函数:

  1. isintance(obj, class_or_tuple) 返回这个对象obj是否是某个类的对象,或者某些类中的一个类的对象,如果是则返回True, 否则返回False
  2. type(obj) 返回对象的类

对象:

  1. 属性(对象拥有的名词) 用实例变量存储
  2. 行为(对象拥有的动作) 用方法表示

  3. 练习:

 1. 定义一个类Huamn(人类)
    有三个属性:
       姓名: name
       年龄: age
       家庭住址: address (可以省略没有)
    有如下方法:
       show_info(self) 用来显示人的信息
       update_age(self) 方法用来让这个人的年龄增加一岁

    def input_human():
        输入下此人的信息,姓名为空结束

    def main():
        docs = input_human()
        for h in docs:
            h.show_info()  # 列出所有人的信息
        for h in docs:
            h.update_age()  # 让所有人都长一岁
        for h in docs:
            h.show_info()  # 再次列表所有人的信息
    main()  # 调用主函数运行

类变量

定义

类变量是类的属性,此属性属于类,不属于此类创建的实例

说明:

  类变量,可以通过该类直接访问
  类变量可以通过该类的实例直接访问
  类变量可以通过此类的对象的 ‘class‘属性间接访问

示例:

  class Human:
      total_count = 0  # 类变量,用于记录对象的个数

  print(Human.total_count)
  h1 = Human()
  print(h1.total_count)  # 0  # 不会出错
  Human.total_count = 1  # 修改类变量
  h1.total_count = 2  #添加了自己的实例属性total_count
  h1.__class__.total_count = 3  # 间接修改类变量
# 此示例示意 类变量的用余和使用方法
class Human:
    total_count = 0  # 类变量,用于记录对象的个数
    def __init__(self, name):
        self.name = name
        self.__class__.total_count += 1  # 人数加人
        print(name, "对象创建")

    def __del__(self):
        self.__class__.total_count -= 1  # 总人数减1

print("当前对象的个数是:", Human.total_count)  # 0
h1 = Human("张飞")
h2 = Human("赵云")
print("当前对象的个数是:", Human.total_count)  # 2
del h2  # 或 h2 = None
print("当前对象的个数是:", Human.total_count)  # 1

类的 slots 属性(有该属性类似java类,不可以动态添加属性)

作用:

  限定一个类创建的实例只能有固定的属性(实例变量)

说明:

__slots__ 属性是一个列表,列表的值是字符串
含有__slots__属性的类所创建的对象没有__dict__字典

示例见:

# 此示例示意__slots__属性的用法
class Student:
    # 限定此的类创建的对象只能有name和age两个属性
    __slots__ = ['name', 'age']

    def __init__(self, n, a):
        self.name = n
        self.age = a


s1 = Student("小张", 20)
# s1.Age = 21  # 此时是错写了age为Age, 会报错
# print(s1.__dict__) # 出错,因为没有__dict__字典

类方法 @classmethod

定义:

类方法是操作类的方法,类方法属于类,不属于该类创建的对象

说明:

类方法需要使用@classmethod装饰器定义
类方法的第一个参数用来绑定类,约定写为cls
类和对象实例都可以调用类方法
类方法不能访问此类创建的对象的属性

示例:

class A:
    v = 0  # 类变量
    @classmethod
    def get_v(cls):  # 此方法不是实例方法,是类方法
        return cls.v

    @classmethod
    def set_v(cls, value):
        cls.v = value

print(A.get_v())  # 0
A.v = 1
print(A.get_v())  # 1
A.set_v(100)
print(A.get_v())  # 100

a = A()  # 创建一个实例
a.set_v(200)
print(A.get_v())  # 200

静态方法 @staticmathod

定义:

静态方法是定义在类的内部的函数,此函数作用域是类的内部

说明:

静态方法需要使用@staticmethod装饰器定义 
静态方法与普通函数的定义相同,不需要传入self和cls
静态方法只能凭借该类和实例来调用
静态方法不能访问类变量和实例变量

示例:

 class A:
        @staticmethod
        def myadd(a, b):
            return a + b

    print(A.myadd(100, 200))
    a = A()
    print(a.myadd(300, 400))

练习:

  修改之前的Human类 让此类能够记录此类生成的对象的个数,
用创建一个类方法get_human_count 来获取’人对象’的个数

继承 inheritance 和 派生 derived

什么是继承 / 派生

继承是从已有类中派生出新类,新类具有原类的数据属性和行为,并能扩展新的能力
派生就是从一个已有的类衍生出新类,在新的类上添加新的属性和行为

作用:

1. 用继承派生机制,可以将一些共有功能加在基类中,实现代码的共享
2. 在不改变超类的代码的基础上,改变原有的功能

名词:

基类(base class) / 超类(super class) / 父类(father class)
派生类(derived class) / 子类(child class)

单继承:

  1. 语法:
    class 类名(超类名):
    语句块
  2. 示例:

      # 此示例示意单继承的语法及使用方法
    class Human:  # 人
        def say(self, what):  # 说话的行为
            print("说: ", what)
    
        def walk(self, distance):  # 走路的行为
            print("走了", distance, "公里")
    
    
    h1 = Human()
    h1.say("今天天气不错!")
    h1.walk(5)
    
    
    print("-------------------")
    class Student(Human):
        # def say(self, what):  # 说话的行为
        #     print("说: ", what)
    
        # def walk(self, distance):  # 走路的行为
        #     print("走了", distance, "公里")
    
        def study(self, subject):
            print("正在学习", subject)
    
    
    s1 = Student()
    s1.say("今天晚饭吃什么?")
    s1.walk(3)
    s1.study("python")
    
    print('------------------------')  
  3. 练习:
      list类里只有append向末尾添加一个元素的方法,但没有向列表部添加元素的方法,试想能否为列表在不改变原有功能的基础上添加一个insert_head(n)的方法,在列表的头部添加元素

    class MyList(list):
    def insert_head(self, element):
    ….
    myl = MyList(range(3, 6)):
    print(myl) # [3, 4, 5]
    myl.insert_head(2)
    print(myl) # [2, 3, 4, 5]

  4. 继承说明:
    任何类都直接或间接的继承自object类
    object类是一切类的超类

  5. 类内的 base属性
      此属性用来记录此类的基类

  6. 见: >>> help(builtins)

覆盖: override

什么是覆盖

  覆盖是指在有继承派生关系的类中,子类中实现了与基类(超类)同名的方法,在子类实例调用方法时,实际调用的是子类中的覆盖版本,这种现象叫做覆盖

示例见:

# 此示例示意B类的work 覆盖A类的work
class A:
    def work(self):
        print("A类的work方法被调用")

class B(A):
    def work(self):
        print("B类的work方法被调用")

b = B()
b.work()  # 子类已经覆盖了父类的方法

问题:

  当覆盖发生时,子类对象能否调用父类中的方法?

super函数

  1. 语法:
    super(type, obj) 返回绑定超类的实例(要求obj必须为type类型的实例)
    super() 返回绑定超类的实例,等同于super(class, 实例的第一个参数), 且必须在方法内调用

  2. 作用:
      返回超类的实例,用超类实例来调用其自身的方法

  3. 示例见:

    
    # 此示例示意用super函数访问父类的覆盖方法
    
    class A:
        def work(self):
            print("A类的work方法被调用")
    
    class B(A):
        def work(self):
            print("B类的work方法被调用")
    
        def doworks(self):
            # self.work()  # 调用B类的
            super(B, self).work()  # 调用超类的方法
            super().work()  # 一样会调用超类的方法
            # super(__class__, self).work()
    
    b = B()
    b.work()  # B类的work方法被调用
    print("-----以下用b调用覆盖版本的方法----")
    
    # A.work(b)  # A类的work方法被调用
    
    super(B, b).work()
    b.doworks()
    
  4. 显式调用基类的初始化方法:
     

    class Human:
        def __init__(self, n, a):
            self.name = n
            self.age = a
            print("Human类的 __init__被调用")
    
        def show_info(self):
            print("姓名:", self.name)
            print("年龄:", self.age)
    
    
    class Student(Human):
        """"""
        def __init__(self, n, a, s=0):
            super().__init__(n, a)  # 显式调用基类的初始化方法
            self.score = s
            print("Student类的 __init__被调用")
    
        def show_info(self):
            super().show_info()
            print("成绩:", self.score)
    
    s1 = Student('张学友', 40)
    s1.show_info()
  5. 说明:
      当子类实现了init方法后,父类的init方法将被覆盖,即不再会主动调用父类的init方法,会引起父类的属性得不到初始化,此时需要显式调用父类的初始化方法

  6. 练习:

    1. 看懂学生管理系统划分模块的依据
    2. 添加保存文件和读取文件的代码
    3. 把字典改为对象来存储数据
      (最好把学生对象的实例变量都封装在类内,让类外的函数最好不要操作这些实例变量)

    4. 练习:
        写一个Bicycle(自行车)类,有run(骑行)方法,调用时显示骑行里程km
      class Bycycle:
      def run(self, km):
      print(“自行车骑行了”, km, “公里”)
      再写一个电动自行车类EBicycle继承自Bicycle,添加电池电量valume属性,同时属有两个方法:
        1. fill_charge(vol) 用来充电,vol 为电量(度)

      1. run(km) 方法用于骑行,每骑行10km消耗电量1度,当电量消耗尽时调用Bicycle的run方法骑行
        并显示骑行结果
        主程序:
          b = EBicycle(5) # 创建一个电动自行车,默认电量5度
        b.run(10)  # 骑行10km
        b.run(100)  # 骑行100km
        b.fill_charge(6) # 充电6度
        b.run(70) # 又骑行70km

猜你喜欢

转载自blog.csdn.net/luohongtucsdn/article/details/80702661