内容目录
一、面向对象
1. 概念
“类”: 具有某些相同属性的一个集合。eg:将“人”定义为一个“类”。
“对象”: 具有某些相同属性的一个集合中的一个元素,某个“类”当中的一个实体。eg:男生。
“面向对象编程”: 是一种封装的思想,它可以更好地模拟真实世界里的事物(将其视为对象)。并把描述特征的数据和代码块(函数)封装到一起。
eg:可以先创建一个“人类”的概念,然后在这个概念当中再创建具体的某一个人(即一个对象),或者多个不同的人(即多个对象)。
最后再定义某个人可以做什么事(即这个人可以实现什么样的功能)。
属性: 类中的所有变量称为属性。(比如人的大脑,四肢,五官等等)
方法: 类中的所有函数通常称为方法。(比如大脑有思考的功能,眼睛可以观看世界等等)
常用名称: class,init,self,object等。
三大特性: 封装,继承,多态。
若在某游戏中设计一个乌龟(turtle)的角色。
使用面向对象的思想会更简单,可以分为如下两个方面进行描述:
- 从乌龟的表面特征(属性)来描述,例如:绿色的、有 4 条腿、重 10 kg、有外壳,等
- 从所具有的的行为(方法)来描述,例如,它会爬、会吃东西
‘’’
将乌龟用代码来表示,
乌龟的表面特征(属性)可以用变量来表示
乌龟的行为特征(方法)可以用函数来表示
'''
class Turtle: # 定义一个Turtle类 一般大写首字母
#定义属性---变量
bodyColor = "绿色" #颜色是绿色
footNum = 4 #有4条腿
weight = 10 #重 10 kg
hasShell = True #有外壳
#定义方法---函数
#会爬
def crawl(self):
print("爬行")
#会吃东西
def eat(self):
print("吃东西")
“类”:
class 类名:
‘’’
类定义的说明文档。主要说明该类的作用,可以通过help函数输出此部分的内容
‘’’
# 类体
‘’’
#此处编写类的属性和方法
‘’’
注意:
1,无论是属性还是方法,对于类来说都不是必需的
2,类中属性和方法的位置是任意的,它们之间并没有固定的前后次序
3,同属一个类的所有属性和方法,要保持统一的缩进格式
4,和变量名一样,类名本质上就是一个标识符,在给类起名时,需要符合标识符的规则
eg: python 允许创建空类,但没有任何意义.
class Person: # 定义一个人类
'''
这是一个Person类的定义
'''
pass
class Person: # 定义一个人类
'''
这是一个Person类的定义
'''
#定义属性---变量
age = 0 # 类属性,表示人的年龄,默认为0岁
name = '某某某' # 类属性,表示人的名字,默认为某某某
weight = 18 # 类属性,表示人的体重,默认为18公斤
#定义方法---函数
def my_name(self):
print('我的名字是:', self.name)
def learn(self):
print("在学习")
def walk(self):
print("在走路")
def think(self, a, b):
print(a, ' + ', b, ' = ', a + b)
def Information(self):
print("%s今年%d岁,体重%d公斤" % (self.name, self.age, self.weight))
# 创建两个“对象”,分别是Someone_1和Someone_2
Someone_1 = Person()
Someone_2 = Person()
# 调用对象的属性:
# 输出属性
print(Someone_1.name)
print(Someone_1.age)
print(Someone_1.weight)
print(Someone_2.name)
print(Someone_2.age)
print(Someone_2.weight)
#调用对象的方法:
Someone_1.my_name()
Someone_1.walk()
Someone_1.learn()
Someone_2.learn()
Someone_2.think(1, 2)
Someone_2.Information()
输出
某某某
0
18
某某某
0
18
我的名字是: 某某某
在走路
在学习
在学习
1 + 2 = 3
某某某今年0岁,体重18公斤
2. 类构造方法
用类创建一个实例对象时,我们希望在创建的同时给对象的某些属性赋一个初值。这就需要在类中添加一个 init() 方法。该方法是一个特殊的类实例方法,称为构造方法(或构造函数)。构造方法用于创建对象时被自动调用。
def __init__(self, ...): # 注意,此方法的方法名中,开头和结尾各有 2 个下划线,
# 且中间不能有空格代码块
注意:
1,即便不添加__init__函数,Python 也会自动为类添加一个仅包含 self 参数的构造方法。
2,仅包含 self 参数的 init() 构造方法,又称为类的默认构造方法。
class Person: # 定义一个Person类
'''
这是一个Person类的定义
'''
def __init__(self): # __init__函数
print("自动调用了构造方法")
def walk(self):
print("可以走路的")
a = Person() # 构建对象的同时直接调用了__init__函数
输出
自动调用了构造方法
在 init() 构造方法中,除了 self 参数外,还可以自定义其它参数。
参数之间使用逗号“,”进行分割。
class Person: # 定义一个Person类
role = 'person' # 类属性,表示人类这个类的role都是person
def __init__(self, name): # __init__函数
print("自动调用了构造方法",name)
def walk(self):
print("可以走路的")
a= Person(name='小强') # 构建对象的同时,给对象的属性name赋值
b= Person(name='小h')
# a= Person('小强') # 构建对象的同时,给对象的属性name赋值
# b= Person('小h') # 去掉name也可以
输出
自动调用了构造方法 小强
自动调用了构造方法 小h
注意:
虽然构造方法中有 self、name这2个参数,但实际需要传参的仅有 name。
也就是说,self 不需要手动传递参数。
class Person: # 定义一个Person类
role = 'person' # 类属性,表示人类这个类的role都是person
def __init__(self, name): # __init__函数
print("自动调用了构造方法",name)
def walk(self):
print("可以走路的")
a= Person(name='小强') # 构建对象的同时,给对象的属性name赋值
b= Person(name='小h')
class Person: # 定义一个Person类
role = 'person' # 类属性,表示人类这个类的role都是person
def __init__(self, name,eight,age,sex,location): # __init__函数
print("自动调用了构造方法",name,eight,age,sex,location)
a= Person('zhangsan',170,30,'man','shanghai')
3. 类对象的创建使用及修改
创建类对象的过程,又称为类的实例化 ,
类对象的创建 : 变量名 = 类名(参数)
定义类时,如果没有添加 init() 构造方法,又或者添加的 init() 中仅有一个 self 参数, 则创建类对象时的参数可以省略不写。
class Person: #定义一个人类
'''
这是一个Person类的定义
'''
# __init__函数,实例化时为每个实例定制自己的属性
def __init__(self, name, age, weight):
self.name = name
self.age = age
self.weight = weight
Someone_1 = Person(name='小强', age=1, weight=18) #类对象的创建 : 变量名 = 类名(参数)
print(Someone_1.name, Someone_1.age, Someone_1.weight)
Someone_2 = Person(name='小杰', age=2, weight=20)
print(Someone_2.name, Someone_2.age, Someone_2.weight)
输出
小强 1 18
小杰 2 20
4. 类对象的使用
类对象名.变量名 #使用英文句点 “.” 来访问对象中的属性(变量)
类对象名.方法名(参数) #使用英文句点 “.” 来访问对象中的方法(函数)
class Person: # 定义一个人类
'''
这是一个Person类的定义
'''
def __init__(self, name, age, weight):
self.name = name
self.age = age
self.weight = weight
def think(self, a, b):
print(a, ' + ', b, ' = ', a + b)
def Information(self):
print("%s今年%d岁,体重%d公斤" % (self.name, self.age, self.weight))
#类对象的使用:调用属性和方法
Someone = Person('小杰', 18, 60) # 创建对象#类对象的创建 : 变量名 = 类名(参数)
print(Someone.name) # 访问类对象的属性,类对象名.变量名
Someone.think(10, 100) # 访问类对象的方法,类对象名.方法名(参数)
Someone.Information() # 访问类对象的方法,由于只有一个self参数,所以不需要传入参数
#类对象的修改:直接赋值
Someone.name = '大杰'
Someone.age = 28
Someone.weight = 80
Someone.Information() #修改后的信息
输出
小杰
10 + 100 = 110
小杰今年18岁,体重60公斤
大杰今年28岁,体重80公斤
注意,Python支持添加新的实例变量或者删除已有的实例变量,也支持给类对象动态添加方法。但是这样就会打乱实例的结构,尽量不用。
5. self使用详解
- 类中的实例属性和实例方法的第一个参数必须是self
def init(self, name, age, weight): - self表征的是当前实例,这样类就能区分当前的实例的内容
self 参数的具体作用是同一个类可以产生多个对象。
class Person: #定义一个人类
def __init__(self, name): # __init__函数,实例化时为每个实例定制自己的属性
self.name = name # 实例属性,表示定义的实例有自己的name
def myself(self):
#myself() 中的 self 代表该方法的调用者,即谁调用该方法,那么 self 就代表谁。
print("this is my self:", self)
Someone_1 = Person(name="小杰")
print("小杰: ", Someone_1)
Someone_1.myself()
print()
Someone_2 = Person(name="大杰")
print("大杰: ", Someone_2)
Someone_2.myself()
输出
小杰: <__main__.Person object at 0x7f5c592184f0>
this is my self: <__main__.Person object at 0x7f5c592184f0>
大杰: <__main__.Person object at 0x7f5c5924e970>
this is my self: <__main__.Person object at 0x7f5c5924e970>
6. 类变量的创建使用及修改
类中变量的类型
- 类体中,所有函数之外:此范围定义的变量,称为类属性或类变量;
- 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
- 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。
6.1 类变量(类属性)
class Person: # 定义一个Person类
'''
这是一个Person类的定义
'''
def __init__(self): # __init__函数
print("自动调用了构造方法")
name = '某某' # 类变量的定义
Someone_1 = Person()
print(Person.name) # 以 “类名.变量” 的方式打印
print(Someone_1.name) # 以 “类对象.变量” 的方式打印
'''
# 类变量在所有实例化对象中是作为公用资源存在的。
# 如果修改了公用资源,则所有对象的变量都一起改变。
Person.name = '小明'
print(Person.name) #结果输出‘小明’
print(Someone_1.name) #结果输出‘小明’
'''
# 而如果只修改了对象的属性,则不会对类变量造成任何影响。
Someone_1.name = '小明'
print(Person.name) #结果输出‘某某’
print(Someone_1.name) #结果输出‘小明’
6.2 实例变量(实例属性):“self.变量名”
注意,实例变量只能通过对象名访问,无法通过类名访问。
class Person: # 定义一个Person类
'''
这是一个Person类的定义
'''
def __init__(self, name): # __init__函数
self.name = name # 实例属性,表示定义的实例有自己的name
def mysay(self):
self.say = "I am instance" # 实例属性也可以定义在实例方法中
Someone_1 = Person(name="小明")
print(Someone_1.name) # 以类对象.变量的方式打印
Someone_1.mysay() # 为了感知实例方法内的实例属性,需要显式的调用实例方法
print(Someone_1.say) # 以类对象.变量的方式打印。
# 思考:如果没有调用mysay()函数,此行会不会报错
# print(Person.name) # 通过类名访问实例变量,会报错
输出
小明
I am instance
6.3 局部变量
直接以“变量名=值”的方式进行定义
class Person: # 定义一个Person类
'''
这是一个Person类的定义
'''
def __init__(self, name): # __init__函数
self.name = name # 实例属性,表示定义的实例有自己的name
def mysay(self):
self.say = "I am instance" # 实例属性也可以定义在实例方法中
def change_name(self):
name = self.name + ' Junior'
# 此行中,等号左边的变量name属于局部变量,右边的属于实例变量
print("局部变量name为:", name)
Someone_1 = Person(name="大雄")
print('实例变量Someone_1.name为:', Someone_1.name) # 实例变量
Someone_1.change_name()
print('调用change_name方法之后:')
print('实例变量Someone_1.name为:', Someone_1.name) # 实例变量未发生任何修改
输出
实例变量Someone_1.name为: 大雄
局部变量name为: 大雄 Junior
调用change_name方法之后:
实例变量Someone_1.name为: 大雄
7. 类的继承
实现继承的类称为子类,被继承的类称为父类(也可称为基类、超类)
子类继承父类时,只需在定义子类的时候,将父类(可以是多个)放在子类之后的圆括号里即可。语法格式如下:
class 类名(父类1, 父类2, ...):
#类定义部分
注意:
1如果该类没有显式指定继承自哪个类,则默认继承 object 类(object 类是 Python 中所有类的父类,即要么是直接父类,要么是间接父类)
所以以下两行定义类的方式是一样的:
class 类名():
#类定义部分
class 类名(object):
#类定义部分
eg:
class People(object):
def say(self):
print("我是一个人,名字是:", self.name)
class Animal(object):
def display(self):
print("人也是高级动物")
class Person(People, Animal): # 同时继承 People 和 Animal 类, 其同时拥有 name 属性、say() 和 display() 方法
pass
Someone_1 = Person()
Someone_1.name = "张三" # 给实例对象赋值
Someone_1.say()
Someone_1.display()
输出
我是一个人,名字是: 张三
人也是高级动物
从结果看出,虽然 Person 类为空类,但由于其继承自 People 和 Animal 这 2 个类,因此实际上 Person 并不空。它同时拥有这 2 个类所有的属性和方法。
eg:多继承顺序
多个父类中包含同名,根据子类继承多个父类时这些父类的前后次序决定.
class People(object):
def __init__(self):
self.name = 'People'
def say(self):
print("People类", self.name)
class Animal(object):
def __init__(self):
self.name = 'Animal'
def say(self):
print("Animal类", self.name)
class Person(People, Animal):
# People中的 name 属性和 say() 会覆盖 Animal 类中的同名属性和方法
pass
Someone_1 = Person()
Someone_1.name = "张三"
Someone_1.say()
输出
People类 张三