Python面向对象之类
- 面向对象编程(oop)是一种程序设计思想。
- oop把对象作为程序的基本单元,一个对象包含数据和操作数据的函数
- 在python中,所有数据类型都被视为对象,也可以自定义对象。
类class
类的定义
- 用来描述具有相同的属性和方法的对象的集合。
- 它定义了该集合中每个对象所共有的属性和方法。
- 类是一个模板,可以用其实例出N多对象。
- 对象是类的实例。
类属性(静态属性)
- 一个对象的特征称为"属性",类中定义的变量通常称为类属性或静态属性。
- 类变量定义在类中且在方法之外,一般定义在类的最上面。
- 类属性存储在类的单独空间,没有实例化对象前就可以使用类属性。
- 单独存在于类中。
- 类中的所有方法、实例都可以使用它。
类属性的定义方式
class 类名:
类属性1 = value
类属性2 = value
类属性的访问方式
- 在类外任意地方通过类名.类属性名访问,或者对象.类属性名访问,但如果对象有同名对象属性,则无法通过对象.类属性名的方式访问到类属性值。
- 在类中任意地方通过类名.类属性名访问。
# 当访问对象属性时,p1.name,p2.name分别先在自己的对象属性中查找。
# 当自己的对象属性中查找不到时,回去类属性查找。
class Person(object):
name = "GaoZhan" # 类属性
age = 25
p1 = Person()
p2 = Person()
print(Person.name, p1.name, id(Person.name), id(p1.name))
p2.name = "LuZhen" # 为p2对象添加了对象属性
Person.name = "GaoYan" # 更改了类属性
print(p2.name, Person.name, id(Person.name), id(p2.name))
print(Person.name, p1.name, id(Person.name), id(p1.name))
result:
GaoZhan GaoZhan 139907955676528 139907955676528 # p1没有对象属性,则去类属性中查找。
LuZhen GaoYan 139907969535312 139907969535368 # p2有自己的对象属性
GaoYan GaoYan 139907969535312 139907969535312 # 类属性更改后, p1.name因为指的还是类属性的地址,所以p1.name的值发生了改变。
类方法
- 类方法(由@classmethod装饰的方法)。
- 可以被类或类的实例对象调用。
- 至少一个cls参数;执行类方法时cls的实际值口为调用该类方法的类。
- 只能操作类的属性或者类方法,不能操作对象的。
class Dog:
def __init__(self, name):
self.name = name
@classmethod
def ability(cls):
print(cls, "It can bark!")
d1 = Dog("WangCai")
Dog.ability()
d1.ability()
result:
<class '__main__.Dog'> It can bark!
<class '__main__.Dog'> It can bark!
对象
对象的定义
- 通过类定义的数据结构实例。
- 对象的实例化就是按照类所创造的模板制造出一个个实物。
- 对象包括的成员为:对象属性和对象方法。
- 每个对象的对象属性和对象方法都属于该对象的单独存储空间,互相无关联。
- 定义对象时的实参直接传递到类的__init__函数的形参上。
对象名 = 类名(参数):
对象(实例)属性
- 类变量是所有实例公用的属性。也就是说一些属性是所有实例都共有的,那么此时我们可以将该属性定义为类属性。
- 如果某些属性是每个实例独有的(每个实例的属性值都不一致),那么我们就可以将这些属性定义为对象属性。
- 每个对象的对象属性和对象方法都属于该对象的单独存储空间,互相无关联。
对象属性的定义方式
- 在类的定义中在初始化__init__函数中定义的变量为对象属性。
- 可以在类的定义外用对象名.属性名在外部增加。
对象属性的访问方式
- 在类定义中任意地方(所有方法中)都可以使用"self.属性名"来调用对象属性。
- 在类定义外任意地方都可以使用"实例名.实例属性名"来调用对象属性。
class Dog:
def __init__(self, name):
self.name = name #在__init__函数中定义对象属性
def ability(self):
print(self, f"{self.name} can bark!") # 当使用d1对象调用的时候,self为d1。
d1 = Dog("WangCai") # 实例化对象
print(d1)
d1.age = 3 # 为d1动态增加对象属性
d1.ability()
print("It is {} years old!".format(d1.age))
result:
<__main__.Dog object at 0x7efdcb503860>
<__main__.Dog object at 0x7efdcb503860> WangCai can bark!
It is 3 years old!
对象方法
对象方法的定义
- 对象方法:不使用装饰器,第一个参数是self
class 类名:
def 函数1(self, 参数1, 参数2):
...
对象方法的访问
- 类中访问对象方法:self.方法名(参数)
- 类外访问对象方法:实例名.方法名(参数)
class Dog:
def __init__(self, name):
self.name = name
def ability(self):
print(f"{self.name} can bark!")
def eat(self, food):
self.ability() # 在类中使用self.方法名访问
print(f"It likes {food}!")
d1 = Dog("WangCai")
d1.ability() # 在类外使用实例名.方法名访问
d1.eat("bones")
result:
WangCai can bark!
WangCai can bark!
It likes bones!
静态方法
- 使用@staticmethod装饰器。
- 没cls和self参数。
- 类的外部可以用类名/对象名.方法访问。
- 使用上和类方法很相似,存在于类存储空间。
- 一般用于和类对象以及实例对象无关的代码。
- 静态方法内部可以访问类属性和类方法,使用类名.类属性/类方法访问。
class Dog:
def __init__(self, name):
self.name = name
def ability(self):
print(f"{self.name} can bark!")
def eat(self, food):
self.ability()
print(f"It likes {food}!")
@staticmethod
def act(act_name):
print(f"I am {act_name}!")
d1 = Dog("WangCai")
d1.ability()
d1.eat("bones")
Dog.act("swimming") #可以使用类名访问
d1.act("swimming") #可以使用对象名名访问
名称 | 应用场景 | 描述 |
---|---|---|
类方法 | 1.只涉及到静态属性的时候可以使用类方法。 2.类方法一般用来修改类属性 | 1.使用@classmethod装饰器。 2.第一个参数cls。 3.类内部通过cls或者类名.方法名访问。 4.类外部通过类名.方法名或者对象名.方法名访问。 |
静态方法 | 1.一般用于和类对象以及实例对象无关的代码。 | 1.使用@staticmethod装饰器。 2.没cls和self参数。 3.类的外部可以用类名/对象名.方法访问。 4.使用上和类方法很相似,存在于类存储空间。 |
对象方法 | 与对象相关的操作 | 1.无装饰器 2.第一个参数self 3.依赖于对象,只有创建了对象后才能使用。 4.类内部使用self.方法名访问,类外部使用类名.方法名访问。 |