一、认识类和对象
(一)类
类就是拥有相同功能和相同属性的对象的集合。
对象就是类的实例
类就是类型,类别
(二)定义类
用代码描述清楚这个类是拥有哪些相同功能,和哪些相同属性的对象的集合。
语法:
'''
语法:
class 类名:
类的说明文档
类的内容
'''
-
**class **- 关键字:固定写法
-
类名 - 程序员自己命名(采用驼峰式命名并且首字母大写。)
-
: - 固定写法
-
类的说明文档 :多行注释
-
类的内容:
1)相同功能和相同属性。
2)由方法(对象方法,类方法,静态方法)和属性(对象属性,类属性)组成。
3)方法 - 定义在类中的函数。
4)属性 - 定义在类中的变量。
案例:
class Person:
'''
说明文档
'''
num = 50 # num是属性
def eat(self): # eat是方法
print('吃饭')
def sleep(self):
print('睡觉')
(三)创建对象
'''
语法:
类名() - 创建指定类对应的一个对象,并且将对象返回
'''
p1 = Person()
p2 = Person()
print(p1)
print(p2) # __main__表示当前模块
二、类中的方法
方法:定义在类中的函数,用来描述具备的功能。
类中的方法有三种:对象方法,类方法,静态方法。
(一)对象方法
- 定义:将函数直接定义在类中。
- 调用:通过对象来调用 - 对象来调用。
- 特点:自带参数self,通过对象调用对象方法的是参数self不需要传参,系统自动传参。
- 什么时候使用:如果实现函数的功能需要用到对象属性就使用对象方法。
def func1(self):
print(f'self:{self}')
print('对象方法')
(二)类方法
- 定义:定义函数前加装饰器’@classmethod’。
- 调用:通过类来调用 - 类名.xxx()。
- 特点:自带参数cls,调用的时候不需要传参,系统自动将当前类传给cls。
- 什么时候用:如果实现函数的功能不需要对象属性需要类就是用类方法。
@classmethod
def func2(cls):
print('类方法')
(三)静态方法
- 定义:定义函数前加装饰器’@staticmethod’。
- 调用:通过类来调用 - 类名.xxx()。
- 特点:没有特点。
- 什么时候调用:实现函数功能既不需要对象属性也不需要类。
@staticmethod
def func3():
print('静态方法')
总:
class A:
def func1(self):
print(f'self:{self}')
print('对象方法')
@classmethod
def func2(cls):
print('类方法')
@staticmethod
def func3():
print('静态方法')
a = A() # 通过对象调用对象方法
a.func1()
A.func2() # 通过类调用类方法
A.func3() # 通过类调用类方法
三、初始化方法
魔法方法:方法名以
'__'
开头并且以'__'
结尾的自带的方法,就是魔法方法。
所有的魔法方法都会特定的情况下被自动调用。
常用的魔法方法:
__init__
方法、__repr__
方法
(一)__repr__
打印对象的时候会自动调用对象对应的类中的
__repr__
方法,来定制打印规则(函数的返回值是什么,对象打印结果就是什么)返回值必须是字符串。
class A:
def __repr__(self):
return 'abc'
pass
a1 = A()
print(f'a1:{a1}') # a1:abc
a2 = A()
print(f'a2:{a2}') # a2:abc
(二)__init__
创建类的对象的时候会自动调用类中的
__init__
方法
案例1:
class B:
def __init__(self):
print('init方法')
b1 = B()
b2 = B()
案例2:
class C:
# 在类中添加__init__方法的时候,除了方法名和方法类型不能动,可以随意添加参数和随意添加函数体
def __init__(self, x, y):
print('C的init方法', x, y)
# 创建类的对象的时候需不需要参数,需要几个参数,由类中__init__方法决定
c1 = C(10, 20)
c2 = C(100, 200)
c3 = C(x=1, y=2)
四、属性
属性分为对象属性和类属性两种。
(一)类属性
- 创建:在类中直接定义变量,这个变量就是类属性。
- 使用:通过类来使用 - 类.xxx。
- 什么时候调用:当属性值不会因为对象不同而不一样的时候就使用类属性。
class A:
# x就是类属性
x = 100
# 使用类属性
print(A.x)
# 修改类属性的值
A.x = 200
print(A.x)
(二)对象属性
- 创建:以’self.属性名 = 值’的形式定义在类的
__init__
方法。 - 使用:通过对象来使用 - 对象.属性名。
- 什么时候使用:当属性值会因为对象不同而不一样的时候就使用类属性。
class A:
# name和num是对象属性
def __init__(self):
self.name = '小明'
self.num = 10
a = A()
print(a.name, a.num) # 小明 10
案例:定义一个圆类,属性:半径和圆周率,拥有的方法:求周长和面积
class Circle:
pi = 3.14
def __init__(self):
self.r = 10
def zhou(self):
return Circle.pi * self.r * 2
def mian(self):
return Circle.pi * self.r ** 2
d = Circle()
print(d.zhou(), d.mian()) # 62.800000000000004 314.0
d2 = Circle()
d2.r = 1
print(d2.zhou(), d2.mian()) # 6.28 3.14
案例:给对象赋初值的方式:
class Person:
def __init__(self, name, gender='男'):
self.name = name # 使用没有默认值的参数来赋值
self.age = 1 # 赋固定值
self.gender = gender # 使用有默认值的参数来赋值
def __repr__(self):
return str(self.__dict__)
p1 = Person('小明')
print(p1.name, p1.gender, p1.age) # 小明 男 1
p2 = Person('小花', '女')
print(p2.name, p2.gender, p2.age) # 小花 女 1
print(p1) # {'name': '小明', 'age': 1, 'gender': '男'}
print(p2) # {'name': '小花', 'age': 1, 'gender': '女'}
案例:定义一个矩形类,属性长、宽,方法:计算面积周长
class Juxing:
def __init__(self, c, k):
self.c = c
self.k = k
def zhou(self):
return self.c * 2 + self.k * 2
def mian(self):
return self.c * self.k
def __repr__(self):
return f'长为:{self.c},宽为:{self.k},面积为:{self.mian()},周长为:{self.zhou()}'
# __dict__是将所有的属性以及值转化为字典
# return str(self.__dict__)
p1 = Juxing(2, 3)
print(p1) # 长为:2,宽为:3,面积为:6,周长为:10
五、属性的增删改查
在面向对象编程的时候,可以直接使用对象来代替字典。
案例:
class Student:
def __init__(self, name, age=18, score=0):
self.name = name
self.age = age
self.score = score
def __repr__(self):
return str(self.__dict__)
stu1 = Student('小明', 12, 67)
stu2 = Student('小花', 19, 100)
print(stu1, stu2) # {'name': '小明', 'age': 12, 'score': 67} {'name': '小花', 'age': 19, 'score': 100}
(一)对象的对象属性支持增删改查
1)查(获取属性值)
- 对象.属性 - 获取指定属性的值,属性不存在报错。
- getattr(对象,属性名) - 获取指定属性的值,属性不存在报错。
- getattr(对象,属性名, 默认值) - 获取指定属性的值,属性不存在直接返回默认值。
print(stu1.name) # 小明
print(getattr(stu1, 'name')) # 小明
# print(stu1.gender) # 报错!
# print(getattr(stu1, 'gender'))
print(getattr(stu1, 'gender', '男')) # 男
2)增、改
-
**对象.属性 = 值 **
当属性存在的时候修改指定属性对应的值;当属性不存在的是给对象添加属性。
-
**setattr(对象, 属性名, 值) **
当属性存在的时候修改指定属性对应的值;当属性不存在的是给对象添加属性。
print(stu1) # {'name': '小明', 'age': 12, 'score': 67}
stu1.age = 22
print(stu1) # {'name': '小明', 'age': 22, 'score': 67}
stu1.gender = '男'
print(stu1) # {'name': '小明', 'age': 22, 'score': 67, 'gender': '男'}
setattr(stu1, 'study_id', '001')
print(stu1) # {'name': '小明', 'age': 22, 'score': 67, 'gender': '男', 'study_id': '001'}
setattr(stu1, 'score', '76')
print(stu1) # {'name': '小明', 'age': 22, 'score': '76', 'gender': '男', 'study_id': '001'}
atr相关函数可以动态操作对象属性
value = input('请输入你想要查看的属性:')
# print(stu1.value)
print(getattr(stu1, value))
3)删
del 对象.属性
delattr(对象, 属性名)
print(stu1) # {'name': '小明', 'age': 22, 'score': '76', 'gender': '男', 'study_id': '001'}
del stu1.age
print(stu1) # {'name': '小明', 'score': '76', 'gender': '男', 'study_id': '001'}
delattr(stu1, 'name')
print(stu1) # {'score': '76', 'gender': '男', 'study_id': '001'}
4)判断属性是否存在
# hasattr(对象, 属性名)
print(hasattr(stu1, 'name')) # False
print(hasattr(stu1, 'score')) # True
if not hasattr(stu1, 'name'):
stu1.name = '小明'
六、继承
让子类直接用拥有父类的属性和方法。
父类就是一个大的类,子类是这个大的类下面的一个小的分类。
语法:
'''
class 类名(父类):
类的说明文档
类的内容
'''
定义类的时候如果没有写父类,这个类默认继承object(基类)。
# class Person: == class Person(object):
class A:
a = 100
def __init__(self):
self.b = 10
self.c = 20
def func1(self):
print('对象方法')
@classmethod
def func2(cls):
print('类方法')
@staticmethod
def func3():
print('静态方法')
class B(A):
pass
print(B.a) # 100
x = B()
print(x.b, x.c) # 10 20
x.func1()
B.func2()
B.func3()
(一)子类添加内容
子类在拥有父类的属性和方法的同时,往往需要由属于自己特有的一些属性和方法。
1)添加类属性和方法
直接在子类中定义新的类属性和新的方法。
2)添加对象属性
需要在子类的__init__
方法中通过super()去调用父类的__init__
方法来继承父类的对象属性。
class C(A):
m = 11
def __init__(self):
super().__init__() # 调用当前类的父类的__init__()
self.name = '小明'
def func11(self):
print('C的对象方法') # 对象方法
@classmethod
def func22(cls):
print('C的类方法') # 类方法
@staticmethod
def func33():
print('C的静态方法') # 静态方法
def func1(self):
print('C的对象方法2')
print(C.a, C.m) # 100 11
x = C()
print(x.name) # 小明
print(x.b, x.c) # 10 20