1. 编程思想的转变
a.面向过程的编程 -- 算法
b.函数式编程 -- 函数/模块
c.面向对象编程 -- 类和对象
2.类、对象
a.定义
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
b.类的声明
1)语法
class 类名:
类的内容
2)说明
- class - 声明类的关键字
- 类名 - 标识符,不能使关键字。见名知义,首字母大写且采用驼峰式命名(e.g:ClassName)
- :- 固定写法
- 类的内容 - 主要包含:类的说明文档、属性(普通的变量)、功能(函数/方法)
c.对象的声明
- 对象 = 类( )- 创建指定的类对应的对象
d.类中的方法
1)什么是方法:声明在类中的函数即方法
2)方法的分类:对象方法、类方法、静态方法
对象方法
- 直接声明在类中的函数
- 有默认参数self,代表类的实例,而非类。不需要为次参数传参,系统将会将当前对象(类的实例)传给self。当前类的对象能做的事,self都能做。
- 通过类的对象调用:Obj.ObjFun()
class Person:
"""人类"""
#========属性========
#========对象方法========
def eat(self, food):
print('人吃'+ food)
self.study()
def study()
print('学习')
p1.eat('苹果') # p1->self 苹果->food
类方法
- 声明函数前加@classmathod
- 有默认参数cls,代表当前类并传给cls
- 通过类来调用:类.类方法()
class Person:
"""人类"""
#========属性========
#========类型方法========
@classmethod
def destroy(cls):
print('人类破坏环境')
Person.destroy()
静态方法
- 声明的函数前加 @ staticmethod
- 没有默认参数
- 通过类来调用:类.静态方法
class Person:
"""人类"""
#========属性========
#========类型方法========
@staticmethod
def beat_animal():
print('人类打架')
Person.beat_animal()
声明类的时候方法的选择
①对象方法:实现函数的功能需要对象属性的时候,就使用对象方法。
②类方法:实现函数功能不需要对象属性,但是需要类的字段,使用类方法。
③静态方法:实现函数的功能既不需要对象属性,也不需要类相关的操作,就使用静态方法。
init方法(构造方法)
-
init是类默认继承的一个魔法方法,用来初始化类 。
-
魔法方法本质是对象方法,但是不需要程序员自己调用,会被自动调用。
-
通过类创建对象的时候(通过构造方法创建对象),系统会自动调用类中的__ init__方法,且将给构造方法的实参传给__ init__方法。
-
创建对象的时候,是否需要参数,决定于__ init__方法
-
(了解)声明类的时候,系统会自动给我们创建一个函数,这个函数的函数名和声明的类的类名一样,这个函数叫构造方法。函数中会先在内存中开辟空间,然后用创建的对象去调用__ init__方法,最后才将对象返回。
e.属性
属性的分类:对象属性、字段
字段
- 直接声明在类中变量就是字段
- 字段要通过“类.字段”的方式来使用
- 当属性的值不会因为对象的不同而不同,这种属性可以声明称类的字段(相对较少)
对象属性
- 必须声明在 __ init__方法中,以‘self.属性 = 值’的形式声明
- 通过‘对象.属性’的方式来使用
- 当属性的值会因为对象的不同而不同的时候,使用对象属性
练习: 声明一个学生类,拥有属性:名字、电话、年龄、学号。拥有功能:学习(打印XXX在学XXX)
class Students:
numbers = 1000
def __init__(self,name, tel, age, number):
self.name = name
self.tel = tel
self.age = age
self.number = number
def study(self, discipline:str):
print('共有'+str(Students.numbers)+'学生')
print(self.name + '在学' + discipline)
student1 = Students('张三', 123, 18, 1)
student1.study('python')
属性的操作
对象的增删改查只针对单个对象
①查
-
对象.属性
如果属性不存在会报错 -
getattr(对象, 属性名, 默认值)
当属性不存在时,有默认值则返回默认值不报错;没有默认值则报错
class Dog:
def __init__(self, name):
self.name = name
self.age = 0
dog1 = Dog('大黄')
print(dog1.name)
# print(dog1.name2) #AttributeError: 'Dog' object has no attribute 'name2'
print(getattr(dog1, 'name2', '无名' ))
②增、改
-
对象.属性 = 值
当属性不存在则添加,属性存在则修改属性的值 -
setattr(对象,属性名, 值)
当属性不存在则添加,属性存在则修改属性的值
dog1.gender = '雌'
print(dog1.gender)
dog1.name = '贝贝'
print(dog1.name)
setattr(dog1, 'name', '白色')
- ③删
- del 对象.属性
- delattr(对象,属性名)
delattr(dog1, 'gender')
del dog1.name
f.内置类的属性
创建类的时候,系统默认为我们添加的类的属性
①__name __:字段
- 获取类的名字
类.__name__
②__doc __:字段
- 获取说明文档
类.__doc__
③__class __:对象属性
- 获取对象的类
对象.__class__
④__dict __:字段/对象属性
- 获取对象的所有属性和对应的值,以字典返回
对象.__dict__
- 获取类中所有字段的和对应的值,以字典返回
类.__dict__
⑤__module __ :字段
- 获取类所在模块的模块名
类.__module__
⑥__bases __ :字段
- 返回当前类的所有父类
类.__bases__
⑥__str __ ; __repr __ (重要) :
- 系统自带的魔法方法,可以定制当前类的对象的打印内容。实现这个函数的时候要求有一个字符串类型的返回值。
#单独打印一个的效果
def __str__(self):
return str(self.__dict__)[1:-1]
# 对象作为元素的时候的打印效果
def __repr__(self):
return 'abc'
⑥slots魔法 :字段
- 可以通过给__ slots__字段赋值,来约束当前类有哪些对象属性
- 当在类中给slots 赋值后,当前类的对象 dict属性无效
__slots__ = ('name', 'age')
G.私有/保护(重要)
- 在很多的高级面向对象语言中,会将属性和方法分为公开的(在类的外部可以使用)、私有的(只能在类的内部使用)、受保护(只能在类的内部使用,可以被继承)的三类。
-
python中类的内容本质上都是公开的。私有和公开都只是约定
私有化 - 效果:内容只能在类的内部使用,不能在外面使用。
- 如何私有化:再类中的方法名或者属性名前加‘__’,对应的属性和方法则会变成私有的。
- 本质:当生命类的时候在名字前加'_',内部会在这个基础前面再加‘类名’。
属性保护 - 可通过在对象属性名前加‘_’,把这个属性标记成受保护类型;为了告诉别人这个属性在使用的时候,不要直接使用,而是通过getter和setter来使用
-
①getter:获取对象的属性值之前想要干点儿别的事情,那么就给这个属性添加getter
- 第一步:属性名前加一个‘_’
- 第二步:在@property后面声明一个函数,这个函数没有参数,有一个返回值,并且函数名是属性名去掉‘_’
- 第三步:获取属性值的时候,通过对象.属性名去掉下划线去获取属性的值
-
②setter:给属性赋值前干别的事情,就给这个属性添加setter。(想要添加setter必须有getter)
- 第一步:属性名前加一个‘_’
- 第二步:在*@getter名.setter后面声明一个函数,这个函数需要一个参数,没有返回值,并且函数名是属性名去掉‘_’
- 第三步:给属性赋值的时候,通过‘对象.属性名去掉下划线 = 值’的方式赋值
#练习:给age属性添加getter和setter,获取年龄的时候拿到年龄值,和这个年龄对应的阶段
#给age赋值的时候必须是整数且范围在0-150,如果不满足要求,报错:AgeError
class AgeError(Exception):
def __str__(self):
return '年龄请输入数字且在0-150之间'
class Human:
def __init__(self):
self._age = 0
@property
def age(self):
if self._age < 18:
return self._age, '少年'
elif 18 <= self._age < 30:
return self._age, '青年'
elif 30 <= self._age < 50:
return self._age,'中年'
else:
return self._age, '老年'
@age.setter
def age(self, x):
if not isinstance(x, int):
raise AgeError
elif not 0 <= x <= 150:
raise AgeError
self._age =x
h = Human()
# h.age =151
# h.age = '10'
h.age = 10
age, jieduan =h.age
print(h.age)
H.继承
①什么是继承:让子类直接拥有父类的属性和方法
- python中所有的类都是直接或间接的继承object
②怎么继承
class 子类(父类列表):
类的内容
③子类中添加内容
-
添加字段和方法:直接添加
-
当父类中有子类中相同的方法:子类中的方法会覆盖父类中的方法,若加入super().方法名()则会保留父类对应方法。
def __init__(self):
super().__init__() #继承父类的__init__
注意:当出现多继承时,会继承所有父类的字段和方法,但是只会继承第一个父类的对象方法
I.运算符重载
- python中所有的类型都是类,所有的数据都是类的对象
-
python使用运算符的时候,实质会去调用这个运算符对应的魔法方法。
类的对象是否支持相应的运算符,就看这个类中国有没有相对应的魔法方法
网友评论