类
类:相似、有公共特征的一类对象。类(class)是许多个体的集合,一个抽象名词、统称。
实例(instance):类中具体的个体叫“对象”、“实例”。举例:水果类包含苹果,梨。电子产品类包含电脑,手机。
对象(object):python万物皆对象,字符串。数字、方法、类实例。
属性(attribute):一类事物的特性叫做属性,例如Student类中的name、score、sex。 类中个体、成员具备的功能、方法叫做成员方法。
# 面向对象
class Student():
def __init__(self, name, score, sex):
self.name = name
self.score = score
self.sex = sex
def print_score(self):
print('{}的成绩是{}'.format(self.name, self.score))
def print_sex(self):
print('{}的性别是{}'.format(self.name, self.sex))
# 实例化
stu1 = Student('小明', 90, '男')
stu2 = Student('小红', 100, '女')
# 调用对象方法
print(stu1.name)
stu1.print_score() # 本质Student.print_score(stu1)
stu2.print_sex()
语法
语法:类关键字class 类名(): 类方法
驼峰命名:每一个单词挨着写并且首字母大写。例如:Electronic_product。
__init__()
:双下划线开头的方法为内置或特殊用途方法。__init__()
又叫做“构造函数”。initial 初始化。类实例化的时候调用__init__()
函数。实例化传入的参数传入init函数,init函数内又赋值给了self对象。为了生成、构造、写信息到一个具体的实例。
self: 自己,指代类自己的某一个实例。好像函数里形参。类里面的每一个函数,都默认传递self参数,self要写在参数的第一位。对象方法调用时,不用传递self参数。
属性、成员方法:访问属性 对象.属性名; 调用成员方法 对象.方法; 写属性 对象.属性名=新值。成员方法把实例中的属性读出来并书写功能。
封装:类的三大特性之一。类的封装比函数的封装更加抽象高级,因为类不光包括功能,还包括数据结构。
类变量和静态方法
命名空间:类封装之后,每个类隔离,可以起相同的属性名,例如name。这样的话,当你引用一个变量,需要告诉解释器这个变量从哪一个大区域来的,这个区域叫做命名空间。
对象变量(类的属性):思维角度针对实例、对象。例如self.name中的name。要先实例化,然后再对对象变量进行读写。print_name()对象方法依然是针对实例的。
类变量(重要):针对每个类,写在类内部。作用域 整个类内使用。语法: 类名.变量名。好像学函数时函数外的全局变量。
静态变量
静态方法 static:静态的意思是一直存在在内存当中,可以随时调用,全局的,不会动态新生成和销毁。类中的静态方法不需要实例化就可以随时调用。
staticmethod装饰器:静态方法通过@staticmethod或@classmethod实现。
区别:@staticmethod不需要self、cls参数。@classmethod第一个参数cls代表类自己,可以在被修饰的方法中调用自己的变量和方法。
cls:当使用@classmethod装饰器的时候,方法的一个参数是cls而不是self。cls(缩写class)就好像self形参指代实例,只是cls指代的是类(代指上例Student类)。
cls的好处是指代类名,好像形参一样,如果类名变化类中代码不需要修改。类似于java中的this。
示例
# 示例
class Student():
student_list = ['小明', '小红'] # 类变量
def __init__(self, name):
self.name = name # 属性,对象变量。
Student.student_list.append(self.name)
def print_name(self): # 对象方法
print('学生姓名:{}'.format(self.name))
@classmethod # @staticmethod
def how_many(cls):
# 判断类内一共多少学生
print('学生总人数:{}'.format(len(cls.student_list)))
def __del__(self):
print('实例被销毁了')
stu_xiaoli = Student('小李')
stu_xiaoli.print_name()
stu_xiaoli.how_many()
print(Student.student_list) # 调用类变量。类.类变量
Student.how_many() # 静态方法调用。类.静态方法
类的继承
class Animal(object):
def __init__(self, name):
self.name = name
def run(self):
print('动物在跑')
class Dog(Animal):
# pass
def swim(self):
print('狗会游泳')
class Cat(Animal):
# pass
def crawl_tree(self):
print('猫会爬树')
def run(self):
print('猫灵活地跑')
dog1 = Dog('臭臭')
dog1.run()
dog1.swim()
cat1 = Cat('小花')
cat1.run()
cat1.crawl_tree()
父类:上例 : 动物类逻辑上、范围上包含Dog、Cat类。那么我们把Animal类叫做“父类”、“超类”、“基类”;Dog、Cat类就叫做“子类”、“衍生类”。
继承inherit:语法 类定义时,类名后面小括号里填写父类名。注意跟类实例化时、函数后面的小括号里的内容不一样。
object:python中变量、方法万物皆对象,现实生活中也是万物皆对象。为了面向对象体系完整,定义了一个默认的、抽象的顶级对象object。
object是所有类的父类。每一个类都默认继承object类,具备一些类的基础方法如__init__
、__del__
。
子类继承父类所有的属性、方法:Dog类实例化用的是父类Animal类中的__init__() run()
。
重写overrides:比如一个父类Animal下有二十个子类Dog、Cat…,这些动物都有run方法,所以公共run方法应该写在Animal类中,但是个别子类run姿势奇特想个性化定义,那么在子类中实现run方法。
子类和父类中出现同名方法,叫做重写。子类中的方法覆盖父类中的同名方法,子类方法生效。
场景:类比较多而且相似的时候,适合抽象为父类、子类,比如游戏。过度抽象可能会使问题更加复杂,不要刻意去使用父类。
好处:类与类关系更加清晰;代码量少;公共部分抽象出来,扩展更方便。
# 多态
class Animal(object):
# def __init__(self, name):
# self.name = name
def run(self):
print('动物在跑')
class Cat(Animal):
def run(self):
print('猫在跑')
class Dog(Animal):
def run(self):
print('狗在跑')
class Pig(Animal):
pass
class Bird(Animal):
pass
class Monkey(Animal):
pass
# 1> 不同的类实例化,实例再调用自己的方法
# cat1 = Cat()
# dog1 = Dog()
# cat1.run()
# dog1.run()
# 2> 把上面的语句封装成函数
def animal_run(class_instance): # 参数接收的是一个类实例
class_instance.run() # 传入cat执行cat.run(),传入dog执行dog.run()
cat1 = Cat()
dog1 = Dog()
animal_run(cat1)
animal_run(dog1)
多态:一段业务逻辑代码,传入的实例不同,最终运行的代码也跟着变化。一种程序可以有多种运行状态,多态。
多态是类的三大特性之一。
好处:减少代码量;代码灵活。