python 类

Posted lxp-never

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 类相关的知识,希望对你有一定的参考价值。

类变量

类变量就类的属性,此属性属于类,不属于此类的实例

作用:通常用来存储该类创建的对象的共有属性

说明:类变量可以通过该类和该类的实例直接访问;类变量可以通过此类的实例对象的__class__属性间接访问

技术分享图片
 1 class Human:
 2     total_count = 0  # 类变量
 3     def __init__(self, name):
 4         print(name, 对象被创建)
 5 
 6 print(Human.total_count)  # 类直接访问类变量 0
 7 h1 = Human(小张)
 8 print(h1.total_count)  # 0 用此类的实例可以访问类变量
 9 h1.total_count = 100  # 为对象添加实例变量
10 print(h1.total_count)  # 100, 优先访问对象的实例变量
11 print(Human.total_count)  # 0, 访问类的类变量
12 print(h1.__class__.total_count) #0 通过此类的实例对象的__class__属性来访问类变量
类变量的访问

类的文档字符串

类内第一个没有赋值给任何变量的字符串为类的文档字符串,类的文档字符串可以用类的 __doc__属性访问

help(Dog)  #查看文档字符串

类的__doc__属性用来绑定文档字符串

类的__slots__列表

作用:限定一个类创建的实例只能有固定属性(实例属性),不允许对象添加列表以外的属性(实例变量)

说明:__slots__列表绑定一个字符串列表,含有__slots__列表的类所创建的实例对象没有__dict__属性,即此实例不用字典来存储对象的属性(实例变量)

技术分享图片
 1 class Human:
 2     # 以下列表限制此类的对象只能有‘name‘ 和‘age‘ 属性
 3     __slots__ = [name, age]
 4 
 5     def __init__(self, name, age):
 6         self.name, self.age = name, age
 7 
 8 
 9 h1 = Human("Tarena", 15)
10 print(h1.age)  # 15
11 # h1.Age = 18  # 出错,h1对象没有Age属性,也不允许有Age属性
12 print(h1.age)  # 15
__slots__ = [" ", " "]

类方法 @classmethod

类方法是用于描述类的行为的方法,类方法属于类,不属于类的实例

说明:类方法需要使用@classmethod装饰器定义

  类方法至少有一个形参,第一个参数用于绑定类,约定写为"cls",类和该类的实例都可以调用类的方法,类方法不能访问此类创建的实例属性,

技术分享图片
 1 class A:
 2     v = 0
 3     @classmethod
 4     def get_v(cls):  # cls 用来绑定调用此方法的类
 5         return cls.v  # 访问类变量
 6     @classmethod
 7     def set_v(cls, value):
 8         cls.v = value
 9 print(A.get_v())  # 0
10 A.set_v(100)
11 print(A.get_v())  # 100
12 a1 = A()  # 创建实例
13 print("a1.get_v() =", a1.get_v())  # 100
14 a1.set_v(200)
15 print("a1.get_v() =", a1.get_v())  # 200
16 print(A.get_v() =, A.get_v())     #200
@classmethod

静态方法  @staticmethod

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

说明:静态方法需要使用 @staticmethod装饰器定义

  静态方法与普通函数定义相同,不需要传入self实例参数和cls参数,静态方法只能凭借该类或类创建的实例调用,静态方法不能访问类变量和实例变量(属性)

技术分享图片
1 class A:
2     @staticmethod
3     def myadd(a, b):
4         return a + b
5 
6 
7 print(A.myadd(100, 200))  # 300
8 a = A()  # 创建实例
9 print(a.myadd(300, 400))  # 700
@staticmethod

实例方法、类方法、静态方法、函数小结

  不想访问类内和实例内的变量,用静态方法

  只想访问类内变量,不想访问实例变量,用类方法

  即要访问内变量,也想访问实例变量用实例方法

  函数与静态方法相同,只是静态方式的作用域定义在类内

继承/派生

继承是指从已有的类中派生出新的类,新类具有原类的行为,并能扩展新的行为

派生类就是从一个已有类中衍生成新类,在新类上可以添加新的属性和行为

作用:1.用继承派生机制,可以将一些共有功能加在基类中,实现代码的共享

  2、在不改变基类的代码的基础上改变原有的功能

名词:基类(base class)/超类(super class)/父类(father class)

  派生类(derived class) / 子类(child class)

单继承:

  语法:

    class 类名(基累名):

      语句块

  说明:单继承是指由一个基类衍生出的新的类

技术分享图片
 1 class Human:  # 人类的共性
 2     def say(self, what):
 3         print("say:", what)
 4 
 5     def walk(self, distance):  # 走路
 6         print("走了", distance, 公里)
 7 
 8 
 9 class Student(Human):
10     def study(self, subject):
11         print("正在学习:", subject)
12 
13 
14 class Teacher(Student):
15     ‘‘‘说话,行走,教学‘‘‘
16     def teach(self, subject):
17         print("正在教:", subject)
18 
19 h1 = Human()
20 h1.say(天气晴了)
21 h1.walk(5)
22 print(---------------)
23 s1 = Student()
24 s1.walk(4)
25 s1.say(感觉有点累)
26 s1.study(Python)
27 print(===============)
28 t1 = Teacher()
29 t1.walk(6)
30 t1.say(吃点啥好呢)
31 t1.teach(面向对象)
32 t1.study(转魔方)
继承

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

类的__base__属性:__base__属性用来记录此类的基类

覆盖

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

技术分享图片
 1 class A:
 2     def works(self):
 3         print("A.works被调用")
 4 
 5 class B(A):
 6     ‘‘‘ B类继承自A类‘‘‘
 7     def works(self):
 8         print("B.works被调用")
 9 
10 b = B()
11 b.works()  # B方法被调用
12 
13 # a = A()
14 # a.works()  # A.works被调用
覆盖
技术分享图片
 1 class A:
 2     def works(self):
 3         print("A.works被调用")
 4 
 5 class B(A):
 6     ‘‘‘ B类继承自A类‘‘‘
 7     def works(self):
 8         print("B.works被调用")
 9 
10 b = B()
11 b.works()  # B.works被调用
12 A.works(b)  # 用类名显式调用, A.works被调用
覆盖

子类对象显式调用基类(被覆盖)方法的方式:基类名.方法名(实例, 实际调用传参)

super 函数

super(cls, obj)返回绑定超类的实例(要求obj必须是cls类型的实例),

super()  返回绑定超类的实例,等同于:super(__class__, 实例方法的第一个参数),必须在方法内调用

作用:借助super() 返回的实例间接调用其父类的覆盖方法

技术分享图片
 1 class A:
 2     def works(self):
 3         print("A.works被调用")
 4 
 5 class B(A):
 6     ‘‘‘ B类继承自A类‘‘‘
 7     def works(self):
 8         print("B.works被调用")
 9 
10     def super_work(self):
11         self.works()  # B.works被调用
12         super(B, self).works()  # A.works被调用
13         super().works()  # A.works被调用
14 
15 
16 b = B()
17 # b.works()  # B.works被调用
18 # super(B, b).works()  # A.works被调用
19 b.super_work()  # ...
20 # super().works() # 出错,只能在方法内调用
sup().父类方法()

显式调用基类的初始化方法

当子类中实现了 __init__方法,基类的构造方法并不会被调用,def __init__(self, ...)

技术分享图片
 1 class Human:
 2     def __init__(self, n, a):
 3         self.name, self.age = n, a
 4         print("Human的__init__方法被调用")
 5 
 6     def infos(self):
 7         print("姓名:", self.name)
 8         print("年龄:", self.age)
 9 
10 class Student(Human):
11     def __init__(self, n, a, s=0):
12         super().__init__(n, a)  # 显式调用父类的初始化方法
13         self.score = s  # 添加成绩属性
14         print("Student类的__init__方法被调用")
15 
16     def infos(self):
17         super().infos()  # 调用父类的方法
18         print("成绩:", self.score)
19 
20 s1 = Student(小张, 20, 100)
21 s1.infos()
super().__init__(n,a)

思考题一

技术分享图片
 1 #    list类里只有一个append向末尾加一个元素的方法,但没有向列表头部添加元素的方法,试想能否为列表在不改变原有类的基础上添加一个insert_head(n) 方法,实现在列表的头部(前部)添加元素
 2 #   如:
 3 #     class MyList(list):
 4 #         def insert_head(self, n):
 5 #             ...  # 需要自己添加代表
 6 
 7 #     myl = MyList(range(3, 6))
 8 #     print(myl)  # [3, 4, 5]
 9 #     myl.insert_head(2)
10 #     print(myl)  # [2, 3, 4, 5]
11 #     myl.append(6)
12 #     print(myl)  # [2, 3, 4, 5, 6]
13 
14 
15 class MyList(list):
16     def insert_head(self, n):
17         # ...  # 需要自己添加代表
18         # self[0:0] = [n]
19         self.insert(0, n)  # 头插
20 
21 
22 myl = MyList(range(3, 6))
23 print(myl)  # [3, 4, 5]
24 myl.insert_head(2)
25 print(myl)  # [2, 3, 4, 5]
26 myl.append(6)
27 print(myl)  # [2, 3, 4, 5, 6]
View Code

思考题二

技术分享图片
 1 #   用类来描述一个学生的信息(可以修改之前写的Student类)
 2 #     class Student:
 3 #          .... 此处自己实现
 4 
 5 #     学生信息有:
 6 #        姓名, 年龄, 成绩
 7 
 8 #     将一些学生的对象存于列表中,可以任意添加和删除学生信息
 9 #       1) 打印出学生的个数
10 #       2) 打印出所有学生的平均成绩
11 #       3) 打印出所有学生的平均年龄
12 
13 
14 class Student:
15     docs = []  # 用来存储所有学生信息(类变量)
16 
17     def __init__(self, n, a, s):
18         self.name, self.age, self.score = n, a, s
19 
20     @classmethod
21     def add_student(cls):
22         s = Student(小张, 20, 100)
23         cls.docs.append(s)
24         s = Student(小李, 18, 98)
25         cls.docs.append(s)
26 
27     @classmethod
28     def get_student_count(cls):
29         return len(cls.docs)
30 
31     @classmethod
32     def get_avg_score(cls):
33         ‘‘‘ 获取所有学生的平均成绩‘‘‘
34         total = 0.0
35         for s in cls.docs:
36             total += s.score
37         return total / len(cls.docs)
38 
39 Student.add_student()  # 添加学生
40 print(当前有%d个学生 % Student.get_student_count())
41 print(当前学生的平均成绩是:, Student.get_avg_score())
View Code

思考题三

技术分享图片
 1 #   用类来描述一个学生的信息(可以修改之前写的Student类)
 2 #     class Student:
 3 #          .... 此处自己实现
 4 
 5 #     学生信息有:
 6 #        姓名, 年龄, 成绩
 7 
 8 #     将一些学生的对象存于列表中,可以任意添加和删除学生信息
 9 #       1) 打印出学生的个数
10 #       2) 打印出所有学生的平均成绩
11 #       3) 打印出所有学生的平均年龄
12 
13 
14 class Student:
15     def __init__(self, n, a, s):
16         self.name, self.age, self.score = n, a, s
17 
18 docs = []  # 用来存储所有学生信息
19 
20 def add_student(lst):
21     s = Student(小张, 20, 100)
22     lst.append(s)
23     s = Student(小李, 18, 98)
24     lst.append(s)
25 
26 def get_student_count(lst):
27     return len(lst)
28 
29 def get_avg_score(lst):
30     ‘‘‘ 获取所有学生的平均成绩‘‘‘
31     total = 0.0
32     for s in lst:
33         total += s.score
34     return total / len(lst)
35 
36 add_student(docs)  # 添加学生
37 print(当前有%d个学生 % get_student_count(docs))
38 print(当前学生的平均成绩是:, get_avg_score(docs))
View Code

 

以上是关于python 类的主要内容,如果未能解决你的问题,请参考以下文章

如何通过单击片段内的线性布局从片段类开始新活动?下面是我的代码,但这不起作用

python 有用的Python代码片段

Python 向 Postman 请求代码片段

python [代码片段]一些有趣的代码#sort

使用 Python 代码片段编写 LaTeX 文档

python 机器学习有用的代码片段