—种程序设计思想,万物皆对象
类和实例
●类:对事物的划分,一类事物拥有共同特征,如人类、学生
●实例:根据类映射出的一个个具体的个吧体(对象),如刘华
●类方法:属于类的功能
●类属性:属于类的属性
●实例方法:属于实例的功能
●实例属性:属于实例的属性
class Student:
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
def eat(self):
print(f"{self.name}吃饭了")
liu_hua = Student("刘华",180,70)
li_ming = Student("李明",177,67)
liu_hua.eat()
li_ming.eat()
__init__
方法:实例初始化方法,创建实例后自动调用,第一个参数self为创建的实例本身
实例属性和类属性
类属性:定义在实例方法外部的属性,所有对象共有,例如:人类共有水资源
实例属性:定义在实例方法内部,对象私有,例如:刘华的钱
class Student:
water = 20
def __init__(self, name, height, weight, food=0):
self.name = name
self.height = height
self.weight = weight
self.food = 10
@classmethod
def drink(cls):
cls.water -= 1
print("喝水")
def eat(self):
self.food -= 1
print("吃饭")
liu_hua = Student("刘华",180,70)
li_ming = Student("李明",177,67)
liu_hua.eat()
print(liu_hua.food)
print(li_ming.food)
liu_hua.drink()
print(liu_hua.water)
print(li_ming.water)
访问限制
以两个下划线开头的属性和方法名是私有属性和私有方法,不能在类的外部访问。
class Student:
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
def eat(self):
self.__drink()
print(f"{self.__name}吃饭了")
def __drink(self):
print(f"{self.__name}先喝口水")
liu_hua = Student("刘华",180,70)
liu_hua.eat()
print(liu_hua.__name)
print(liu_hua.__drink)
如果外部代码要获取私有属性,可以定义方法,如: get_name;也可以利用装饰器@property
def get_name(self):
return self.__name
@property
def name(self):
return self.__name
print(liu_hua.get_name())
print(liu_hua.name)
liu_hua.name = "jack"
如果外部代码要修改私有属性,可以定义方法: set_name;也可以利用装饰器`@xxx.setter: @name.setter`
def get_name(self, name):
self.__name = name
@name.setter
def get_name(self, name):
self.__name = name
liu_hua.set_name("jack")
liu_hua.name = "jack"
print(liu_hua.name)
为什么通过定义方法设置私有属性,不直接赋值?可以参数检查
私有属性能直接访问吗?`__name`不能访问是因为Python解释器把`__name`改成了_Student__name。
类的内置属性
●`__dict__`:类的属性(包括一个字典,由类的数据属性组成)
●`__doc__`:类的文档字符串
●`__name__`:类名
●`__module__`:类定义所在的模块(类的全名是`__main__.className`,如果类位于一个导入模块`mymod`中,那么`className.__module__`等于`mymod`)
● `__bases__` :类的所有父类构成元素(包括了一个由所有父类组成的元组)
`●__mro__`:显示继承顺序
class Student:
"""
学生类
"""
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
def eat(self):
self.__drink()
print(f"{self.__name}吃饭了")
def __drink(self):
print(f"{self.__name}先喝口水")
liu_hua = Student("刘华",180,70)
print(Student.__dict__)
print(Student.__doc__)
print(Student.__name__)
print(Student.__module__)
print(Student.__bases__)
继承
面向对象的编程带来的主要好处之一是代码的重用,实现重用的方法之一是通过继承机制。
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。私有的属性、方法,不会被子类继承,也不能被访问。
class Animal:
def __init__(self, weight, height):
self.height = height
self.weight = weight
def eat(self):
print('吃食物')
class Cat(Animal):
def call(self):
print("喵喵叫")
class Dog(Animal):
def call(self):
print("汪汪叫")
cat1 = Cat(5,20)
cat1.call()
dog1 = Dog(10,30)
dog1.call()
dog1.eat()
print(dog1.weight, dog1.height)
方法重写
父类方法不能满足需求时,子类可以重写方法
class Animal:
def __init__(self, weight, height):
self.height = height
self.weight = weight
def eat(self):
print('吃食物')
class Cat(Animal):
def call(self):
print("喵喵叫")
def eat(self):
print("吃猫粮")
cat1 = Cat(5,20)
cat1.call()
调用父类方法
保留父类的属性并新增属性(初始化方法),或保留父类某个方法的功能并增强调用方法:
super(子类名,self).方法名(参数)super().方法名(参数)
父类名.方法名(self,参数)
class Animal:
def __init__(self, weight, height):
self.height = height
self.weight = weight
def eat(self):
print('吃食物')
class Cat(Animal):
def __init__(self, weight, height, color):
super().__init__(weight, height)
self.color = color
def eat(self):
super().eat()
# super(Cat, self).eat()
# Animal.eat(self)
print('喝点水')
cat1 = Cat(5,20, 'white')
cat1.eat()
多继承
括号中使用逗号分隔多个父类
多个父类中有相同的方法名,并且子类中没有该方法时,从左到右查找父类中的该方法。
class People:
def __init__(self, height, width):
self.height = height
self.width = width
@staticmethod
def working():
print("工作中")
class Worker(People):
@staticmethod
def working():
print("搬砖中")
class Women(People):
@staticmethod
def working():
print("购物中")
class WomenWorker(Worker, Women):
pass
ww = WomenWorker(170, 50)
ww.working()
print(WomenWorker.__mro__)