python面向对象基础(二)

python面向对象对象基础(一)内容回顾:

  • 面向对象组织代码:降低耦合度(耦合度指各个对象之间的关联关系),界限分明;
  • 使用class语句创建类;
  • 构造函数的调用:类名(调用实参),用来实例化(创建)一个对象;
  • 类中的3种方法:
  1. 实例方法:描述类有哪些行为;
  2. 初始化方法:def __init__(self, 形参列表):
  3. 析构方法:def __del__(self):
  • 实例属性:每个对象用于绑定自己数据的变量叫实例变量,也叫属性;
  • 每个对象都具有特殊属性:__dict__   &&   __class__

    2 个函数    
        isinstance(obj, 类或元组)
        type(obj)

一. 类变量

1. 概念

  • 定义:类变量是类的属性,此属性属于类,不属于类的实例;
  • 作用:通常用来存储该类对象共有的数据;
  • 说明:
  1. 类变量可以通过属性直接访问:Human.total_count += 1;
  2. 类变量可以通过类的实例直接访问;
  3. 类变量可以通过此类的对象的__class__属性直接访问;
  4. 语法:

        class 类名(继承列表):
            类变量名 = 表达式
            ... 

示例代码:

class Human:
    """示意类变量的用法,以及类和对象的关系"""
    # 类变量,记录所有实例对象的个数
    total_count = 0

    def __init__(self, n):
        """对象在创建时,自动被调用"""
        self.name = n
        # 如果一个对象诞生,则将类变量total_count做+1操作
        self.__class__.total_count += 1

    def __del__(self):
        """对象在销毁时,自动被调用"""
        self.__class__.total_count -= 1


if __name__ == "__main__":
    # 类变量可以通过属性直接访问
    Human.total_count += 1
    print('Human类内的类变量 total_count =', Human.total_count)

    # 类变量可以通过类的实例直接访问(实例对象的__class__属性绑定了创建它的类)
    h1 = Human('Alex')
    print('Human类内的类变量 total_count =', h1.total_count)

    # __dict__属性存储了自定义的实例变量
    print(h1.__dict__)

    # 为当前的实例添加一个变量,并不是修改类变量
    h1.total_count = 100
    print('Human类内的类变量 total_count =', Human.total_count)
    print('h1的实例变量 total_count =', h1.total_count)
    print(h1.__dict__)

    # 修改类变量的值
    h1.__class__.total_count = 200
    print('Human类内的类变量 total_count =', Human.total_count)

    del h1
    print('Human类内的类变量 total_count =', Human.total_count)

运行结果:

2. 类的__slots__属性

  • 作用:限定一个类创建的实例只能有固定的属性(实例变量),不允许对象添加列表以外的属性;防止用户因错写属性的名称而发生程序错误;
  • 说明:含有__slots__属性的类所创建的实例没有__dict__属性,即此实例不用字典来存储实例变量;
  • 示例:
"""__slots__ = ['name', 'age']
此列表让Student创建的对象只能用name属性和age属性,不能有其它属性。
"""


class Student:
    """示意__slots__属性的作用和用法"""
    __slots__ = ['name', 'age']

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


if __name__ == "__main__":
    s1 = Student('Alex', 22)
    print(s1.age)
    print(s1.name)
    # AttributeError: 'Student' object has no attribute 'country'
    s1.country = "China"

备注:类的文档字符串是类内没有赋值给任何变量的字符串,由类的__doc__属性绑定。

二. 类方法

  • 类方法:用于描述类的行为,此方法属于类,不属于该类创建的实例;
  • 说明:
  1. 类方法需要使用@classmethod装饰器定义;
  2. 类方法至少有一个形参,第一个形参用于绑定类,约定为:'cls';
  3. 类实例和对象实例都可以调用类方法;
  4. 类方法不能访问实例属性和方法;
  • 示例:
"""类方法的使用"""


class A:
    """docstring for A"""
    # 类变量v
    v = 0

    def __init__(self):
        # __init__定义的为实例变量,属于类的实例
        self.my_v = 10000000

    # 类方法需要使用@classmethod装饰器定义
    @classmethod
    # 类方法至少有一个形参,第一个形参用于绑定类,约定为:'cls'
    def get_v(cls):
        """此方法为类方法,cls用于绑定调用此方法的类;此方法用于返回类变量v的值"""
        return cls.v

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


if __name__ == "__main__":
    # 通过类实例来调用类方法
    print(A.get_v())
    A.set_v(100)
    print(A.get_v())

    # 通过对象实例调用类方法
    a = A()
    print(a.get_v())
    a.set_v(200)
    print(a.get_v())

    # 访问实例属性
    print(a.my_v)

三. 静态方法

  • 静态方法:定义在类内的函数,此函数的作用域是类的内部;
  • 说明:
  1. 静态方法需要使用@staticmethod装饰器定义;
  2. 静态方法与普通函数定义相同,不需要传入self实例参数和cls参数;
  3. 静态方法只能凭借该类或类的实例来调用;
  4. 静态方法不能访问类变量和实例变量(属性)。
  5. 静态方法仅仅是属于一个类,和普通的函数是一样的
  • 小结:实例方法,类方法,静态方法(面向对象编程);函数,和对象无关的,面向过程编程。

示例:利用类方法和静态方法重写学生类

"""用类来描述一个学生的信息
学生信息:name age score
要求:
    1.将这些学生信息存于列表中,可以添加和删除学生信息;
    2.打印学生的个数;
    3.打印出所有学生平均成绩;
    4.打印出所有学生的平均年龄;
建议用类变量存储学生的个数
"""


class Student:
    """描述学生的信息"""
    count = 0

    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score
        # 每创建一个对象,类变量count自动加1
        self.__class__.count += 1

    def get_name(self):
        return self.name

    def get_age(self):
        return self.age

    def get_score(self):
        return self.score

    @classmethod
    def get_stu_number(cls):
        """只访问类变量,使用类方法即可"""
        return cls.count

    @staticmethod
    def average(students, kind):
        """不需要访问实例变量和类变量,仅仅是定义在类内的函数,使用静态方法即可"""
        sum_kind = 0
        for student in students:
            if kind == 'score':
                sum_kind += student.get_score()
            elif kind == 'age':
                sum_kind += student.get_age()
        average = sum_kind // Student.get_stu_number()
        return average

    @staticmethod
    def add_stu_info():
        """一次性录入所有的学生信息,并以列表形式返回所有创建好的学生实例"""
        students = []
        while True:
            name = input('输入姓名:') or 'q'
            if name == 'q':
                break
            age = int(input('输入年龄:'))
            score = int(input('输入成绩:'))
            student = Student(name, age, score)
            students.append(student)
        return students

    @classmethod
    def remove_student(cls, name, students):
        """根据姓名删除列表中的学生"""
        for student in students:
            if student.get_name().lower() == name.lower():
                stu_list.remove(student)
                cls.count -= 1
        else:
            # for ... else ...语句
            # 当学生列表为空时执行
            print('学生信息不存在!')


if __name__ == "__main__":
    # 录入学生信息
    stu_list = Student.add_stu_info()
    for s in stu_list:
        print(s.get_name(), s.get_age(), s.get_score())

    # 调用静态方法,计算平均成绩
    score_average = Student.average(stu_list, 'score')
    print(Student.get_stu_number(), '个学生的平均成绩为:', score_average)

    # 调用静态方法,计算平均年龄
    age_average = Student.average(stu_list, 'age')
    print(Student.get_stu_number(), '个学生的平均年龄为:', age_average)

    # 删除列表中的学生
    name = input('请输入要删除学生的姓名:')
    Student.remove_student(name, stu_list)
    print(Student.get_stu_number())
    for s in stu_list:
        print(s.get_name(), s.get_age(), s.get_score())

运行结果:


四. 特性属性 @properity

  • 实现其它语言所拥有的getter 和 setter 功能;
  • 作用:用来模拟一个属性,通过@properity装饰器可以对模拟的属性赋值和取值加以控制;
  • 用法一:score = property(get_score, set_score)
class Student:
    def __init__(self, score):
        self.__score = score

    def get_score(self):
        """实现getter"""
        return self.__score

    def set_score(self, s):
        """实现setter"""
        if 0 <= s <= 100:
            self.__score = s
        else:
            raise ValueError

    score = property(get_score, set_score)


s = Student(59)
print(s.score)
s.score = 88
print(s.score)

  • 使用方式二:@property、@score.setter
class Student:
    def __init__(self, score):
        self.__score = score

    @property
    def score(self):
        """实现getter"""
        return self.__score

    @score.setter
    def score(self, s):
        """实现setter"""
        if 0 <= s <= 100:
            self.__score = s
        else:
            raise ValueError


s = Student(59)
print(s.__dict__)
print(s.score)
s.score = 97
print(s.score)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值