本次内容:面向对象
大量高能预警
>> Python每日笔记—目录 <<
面向对象:
面向对象技术简介:
类(Class):用来描述具有相同属性的方法的对象的集合
对象:是类的实例
方法(function):类中定义的具有一定功能的函数。
类变量:类变量在整个实例化的过程当中是共用的。类变量定义在类中,且在函数体的外面。
类变量通常被实例变量使用。
数据成员:类变量或者实例变量用于处理类及其相关对象的数据。
重写方法:重写同名的方法
局部变量:方法内的变量
实例变量:在类的声明中,属性用变量来表示,称为实例变量。实例变量就是一个用self修饰的变量
继承:一个派生类(子类)继承一个积累(父类),可以继承父类的属性和方法。继承允许吧一个紫烈的对象
作为一个父类的对象对待。(允许多继承的存在,一个类可以继承多个父类)
实例化:创建一个类的实例,具体的类的对象
对象:通过类定义的结构的实例。对象包括两个数据成员:类变量和实例变量、方法
私有属性:
__private_attrs:两个下划线开头,声明该属性为私有,必能在类的外部所需使用或直接访问
在类的内部时候访问:self.__private__attrs
**类的专有方法**:
__init__():构造方法,在生成对象的时候调用
__del__():析构函数,释放对象的时候调用
__repr__():打印,转换
__setitem__():按照索引赋值
__getitem__():根据索引取值
__add__():加运算
__sub__():减运算
__mul__():乘运算
__div__():除运算
__mod__():求余数运算
__pow__():次方运算
self 和 构造方法
- self等同于Java和C++中的this关键字,self代表类的实例(当前对象),而不是类,但是self不是关键字,也就是说在参数列表中可以自己命名self。
- 类方法和普通方法的区别:类方法里有额外参数self
- 构造方法__init__: 和java中类的构造方法一样,用于初始化对象,可以设置参数
class MyClass:
i = 1000
'''类的介绍,简单类的实例'''
def f(self): # self(自身)自动生成,且调用时不需要参数
# 默认的是self,可以修改
return "Hello,world"
# 和java中类的构造方法一样,用于初始化对象
def __init__(self):
print("这是构造方法")
if __name__ == '__main__':
'''创建一个类的实例'''
x = MyClass() # print"这是构造方法"
# 通过该MyClass的对象访问属性
print(x.i) # 1000
# 通过该MyClass的对象访问方法
print(x.f()) # Hello,world
私有属性 和 继承关系
- 私有属性就是在属性名前面加双下划线__,私有属性同Java中的private一样,不能直接通过对象名访问,需要调用方法访问私有属性。
class people:
# 定义基础属性
name = ''
age = 0
# 定义私有属性
__weight = 0
# 定义构造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s说: 我今天%d岁了,体重%dKG" % (self.name, self.age, self.__weight))
'''实例化people,使用实例化对象访问speak函数'''
P = people("大火", 38, 75)
P.speak()
'''私有属性不能直接访问,私有属性要用函数去访问!'''
# print(P.__weight)
- 继承:Python中支持多继承关系,子类可以继承父类中的方法和变量,如下给出一个例子:
class people:
# 定义基础属性
name = ''
age = 0
# 定义私有属性
__weight = 0
# 定义构造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s说: 我今天%d岁了,体重%dKG" % (self.name, self.age, self.__weight))
class person:
id = 0
address = ''
def __init__(self, id, a):
self.id = id
self.address = a
def speak(self):
print("这是person中的speak方法")
class student(people, person): # student作为people的子类继承
grade = ''
def __init__(self, n, a, w, g, id, address):
# 调用父类的构造函数
people.__init__(self, n, a, w)
person.__init__(self, id, address)
self.grade = g
def speak(self):
print("%s说: 我今天%d岁了,在读大%d年级" % (self.name, self.age, self.grade))
if __name__ == '__main__':
'''实例化student对象,并访问speak方法,测试该speak方法是父类还是子类的? 子类,子类中重写的speak的方法'''
# S = student("小火", 20, 75, 3)
# S.speak() # 子类的speak方法
'''多继承传参测试
进行这项案例是,需要将student中的speak函数注释掉'''
S2 = student("小火", 20, 75, 3, 101, "中国")
S2.speak() # 小火说: 我今天20岁了,体重75KG
# 在继承的情况下, 调用父类中重名方法的时候,默认调用的是在继承的括号中靠前的方法
# 样例中输出了people的speak,但没有输出person的speak
- super关键字:
如果你具有其他对象对象语言的基础,你应该思考,子类如何调用父类的方法或者变量呢? super关键字
class Parent: # 父类
def my_method(self):
print("调用父类的方法")
class Child(Parent):
def my_method(self):
print("调用子类的方法")
c = Child()
c.my_method()
# 想用子类对象调用父类中被覆盖的方法
# super()可以调用父类的方法,参数1 = 类名, 参数2 = 对象名
super(Child, c).my_method()
super还可以在函数体内调用父类的方法或者变量:
'''
super()是用于调用父类的一个方法
super()是用来解决多重继承问题,直接用类名调用父类方法使用单继承的时候没有问题
在多继承的情况下,会涉及到查找顺序,还有重复调用等问题
'''
class A:
def add(self, x):
y = x + 1
print(y)
class B(A):
def add(self,x):
# 直接使用super相当于调用父类中的方法
super().add(x)
# 完整写法
super(B, self).add(x)
if __name__ == '__main__':
b = B()
b.add(4) # 5
- 子类如何调用父类中的构造方法(init)呢?
'''
如果在子类当中需要父类的构造方法,
1、显示调用
2、不重写父类的构造方法
子类不重写__init__,实例化子类的时候,会自动调用父类的__init__方法
'''
class Father(object):
def __init__(self, name):
self.name = name
print('name=%s' % self.name)
def getName(self):
print('Father', self.name)
class Son(Father):
def __init__(self, name):
# 两种调用父类的构造函数的方法
super(Son, self).__init__(name)
# Father.__init__(self, name)
print("测试")
def getName(self):
print('Son', self.name)
if __name__ == '__main__':
# 测试如何调用父类的方法
# s = Son() 报错,原因:调用父类的构造函数需要参数
s = Son('小火') # name=小火
# 如果子类没有构造函数,会自动调用父类里的构造函数
- 私有方法和私有变量
私有方法同私有变量的写法一样都是在前面加双下划线__
在类外部,不能直接访问私有变量
在类外部,不能直接调用私有方法
给出一个案例:
class JustCounter:
__se = 0 # 私有变量
public = 0
def count(self):
self.__se += 1
self.public += 1
print(self.__se)
def __pre(self): # 私有方法
self.__se += 1
self.public += 1
print(self.__se)
just = JustCounter()
just.count() # 1
# print(just.__se) 在类外部,不能直接访问私有属性
# just.__pre 在类外部,不能直接调用私有方法
- 方法的重写
思考一下,为什么 print(t.sum(2, 3))会报错?
因为,sum的方法已经被重写,参数个数不一致。
class test:
def sum(self, num1, num2):
return num1 + num2
def sum(self, num1, num2, num3):
return num1 + num2 + num3
t = test()
# print(t.sum(2, 3)) 报错
print(t.sum(2, 3, 4))
- 类的方法和静态方法:
这两个方法极其相似,但仍然有区别:
静态方法 | 类的方法 |
---|---|
静态方法装饰器下定义的方法属于函数(function); | 类方法装饰器下定义的方法属于方法(method); |
静态方法无需传入任何参数; | 类方法传入的第一个参数必须是class本身cls; |
使用@classmethod声明 | 使用@staticmethod声明 |
共同点 |
---|
静态方法与类方法一旦被调用,内存地址即确定。通过类调用和通过实例化对象调用的结果完全一样。 |
类方法案例:
'''
需要使用装饰器@classmethod来标识为类的方法
第一个参数必须是类对象,一般以cls作为第一个参数
'''
class Dog(object):
__tooth = 10
@classmethod
def get_tooth(self):
return 0
def test(self):
print("测试")
# 2、创建对象,调用类方法
g = Dog()
result = g.get_tooth()
result = Dog.get_tooth()
# Dog.test() # 报错
# Dog.test(g) # 不会报错
print(result)
静态方法案例:
'''静态方法
静态方法使用@staticmethod来修饰,静态方法不需要传递类对象,也不需要传递实例对象(形参self/cls)
静态方法可以通过实例对象和类对象访问
减少不必要的内存占用和性能消耗
'''
class test(object):
@staticmethod
def info_print():
print("这是一个静态方法")
t = test()
t.info_print() # 这是一个静态方法
test.info_print() # 这是一个静态方法 静态方法可以直接类名访问
单选/多选题(使用继承的方法)
1、输入题目和备选答案
2、预设答案
3、使用前面的可变参数
4、调用对象的方法进行对比
class Select:
title = ""
options = ""
answers = []
def set_titile(self):
self.title = input("请输入题干")
def set_option(self):
self.options = input("请输入选项")
def set_answers(self, *answer):
for i in range(len(answer)):
self.answers.append(i)
def check(self, submits):
for i in range(len(submits)):
flag = 1
for j in range(len(self.answers)):
if submits[i] == self.answers[j]:
continue
else:
flag = 0
if flag == 0:
return "回答错误"
else:
return "回答正确"
def begin(self):
print(self.title)
print(self.options)
class One(Select):
def set_titile(self):
super(One, self).set_titile()
def set_option(self):
super(One, self).set_option()
def set_answers(self, *answers):
super(One, self).set_answers()
def begin(self):
super(One, self).begin()
class Two(Select):
def set_titile(self):
super(Two, self).set_titile()
def set_option(self):
super(Two, self).set_option()
def set_answers(self, *answers):
super(Two, self).set_answers()
def begin(self):
super(Two, self).begin()
if __name__ == '__main__':
s = One()
s.set_titile()
s.set_option()
s.set_answers('A')
s.begin()
sub = input("请输入答案")
print(s.check(sub))
s2 = Two()
s2.set_titile()
s2.set_option()
s2.set_answers('A', 'B')
s2.begin()
sub = input("请输入多选答案")
print(s2.check(sub))
tips: 方法和函数有所不同,方法是对象的函数。
周末休两天,没有内容了周一再更,朋友们可以关注本栏目,持续更新ing
如果这篇文章对你有帮助的话,点个赞呗