class Person: h_type='人类' #让对象拥有独有的数据 def __init__(self,name): self.name=name #定义在类中的函数,称为方法 '多个对象公共的方法 也算多个对象独有的方法。当有对象来调用就会将该对象当作第一个参数传入' def eat(self): print('%s正在吃饭'%self.name) def others(self,a,b): print('对象调我需传两个参数,类调我需传三个') p1=Person('jason') p1.eat()#jason正在吃饭 对象调用不用传参数 p2=Person('osrcar') Person.eat(p2)#osrcar正在吃饭 类调用需把对象当第一参数传入 '对象调用,不用传参' '类调用,需手动输入对象为第一参数,如果有参则需要手动传入' p1=Person('jason') p1.others(1,2)#对象调我需传两个参数,类调我需传三个 Person.others(p1,1,2)#对象调我需传两个参数,类调我需传三个
专门针对在类体代码中编写的函数 1.绑定给对象的方法 self用于接收对象 对象调用会自动将对象当做第一个参数传入 类调用则需要手动将对象当第一参数,其他有几个形参就传几个实参 2.绑定给类的方法 cls用于接收类 @classmethod (需创建一个内置装饰器) 对象调用会自动将产生该对象的类当作第一个参数传入 类调用会自动将类当作第一个参数传入 3.静态方法(普普通通的函数) @staticmethod (调用静态方法) 类或对象都需要按照指定对应的参数传入,有多少参数就传多少个参数。
class Student: school = '清华大学' # 绑定给对象的方法 def run(self): # self用于接收对象 print('跑', self) @classmethod # 绑定给类的方法 def eat(cls): # cls用于接收类 print('吃', cls) @staticmethod # 静态方法 def sleep(a, b): # 无论谁来调用都必须按照普通的函数传参方式 print('睡觉') 调用: stu1 = Student() '调用绑定给对象的方法' stu1.run() #跑 <__main__.Student object at 0x000001E051FF9E50> Student.run(stu1) #跑 <__main__.Student object at 0x000001E051FF9E50> '调用绑定给类的方法' Student.eat() #吃 <class '__main__.Student'> stu1.eat() #吃 <class '__main__.Student'> '调用静态方法' Student.sleep(1,2) #睡觉 stu1.sleep(1, 2) #睡觉
面向对象三大特征:继承、封装、多态
继承 | 含义 | 目的 |
---|---|---|
现实 | 用来描述人与人之间资源的关系 | 想占有别的的财产 |
编程 | 描述类与类之间数据的关系 | 为了节省代码编写 |
继承的操作: eg: class Father: money=1000 def car(self): print('有很多车') #Son继承Father里的东西 class Son(Father): pass print(Son.money)#1000 Son.car(1)#有很多车 ———————————————————————————————————————— class 类名(要继承的类名): pass 1.定义类的时候在类名后加括号 2.括号内填需要继承的类名 3.括号内可填写多个父类,逗号隔开 注意: 被继承的类称之为: 父类或基类或超类 继承类的类称之为: 子类或派生类 常用 父类和子类 class MyClass(F1,F2,F3) pass 注意:多个父类中查找数据,默认是从左到右依次查找对应的属性 如果自己就有这个数据,则是先找自己要
继承的本质: 抽象:将多个类共同的数据或功能抽取出来形成一个基类 继承:从上往下白嫖各个基类里面的资源 (就是把相同的代码抽出来变成一个父类,其他要调用时变成子类就可以调用父类中的资源) """ 对象:数据和功能的结合体 类:多个对象相同的数据和功能的结合体 父类:多个类相同的数据和功能的结合体 ps:类和父类最主要的功能其实就是节省代码 """
1.不继承的情况下名字查找顺序 先从对象自身查找,没有再去产生该对象的类中查找 class Student: school = '清华大学' def choice_course(self): print('正在选课') stu1 = Student() print(stu1.school) # 清华大学 对象查找school 自身名称空间没有 所以查找的是类的 stu1.school = '北京大学' # 在自身的名称空间中产生了新的school """对象点名字并写了赋值符号和数据值 那么操作的肯定是自己的名称空间""" print(stu1.school) # 北京大学 print(Student.school) # 清华大学 查找顺序: 对象 >>> 类
2.单继承的情况下名字查找顺序 先从对象自身查找 没有再去产生该对象的类中找 没有再去父类中找(每次查找完一个都会回到最初始的位置再查找一次) class A: name='from A' class B(A): name='from B' class C(B): name='from C' class MyClass(C): name='from MyClass' obj=MyClass print(obj.name)#from MyClass 查找顺序: 对象 >>> 类 >>> 父类 —————————————————————————————————————————————— class A1: def func1(self): print('from A1 func1') def func2(self): print('from A1 func2') self.func1() class MyClass(A1): def func1(self): print('from MyClass func1') obj = MyClass() obj.func2()#from A1 func2 from MyClass func1 #注意:只要涉及到对象查找,每次查找都会回到最初始的位置依次查找 要明确对象(self)是来自哪个类,哪个类调用就从哪个对象里找,然后再从产生该对象的类中找,然后再去父类中找
3.多继承的情况下名字查找顺序 非菱形继承(最后不会归总到一个我们自定义类上) 深度优先(每个分支都走到底 再切换) 菱形继承(最后归总到一个我们自定义类上) 广度优先(前面几个分支都不会走最后一个类 最后一个分支才会走) #也可以使用 print(类.mro()) 方法查看该类产生的对象名字的查找顺序
#object里有类必备的所有功能 经典类 不继承object或其子类的类(什么都不继承) 新式类 继承了object或其子类的类 """ 1.在python3中只有新式类 所有的类默认都会继承object 2.在python2中有经典类和新式类 由于经典类没有核心的功能 所以到了python3就没有了 3.以后在定义类的时候,如果没有想要继承的父类 一般推荐以下写法: class MyClass(object): pass 目的是为了兼容python2 """
子类中定义类与父类一模一样的方法并且扩展了该功能>>>:派生 '又想用别人的方法,又觉得别人的方法不够' class Person: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class Teacher(Person): def __init__(self, name, age, gender, level): # super专门用于子类调用父类的方法 super().__init__(name, age, gender) #自己再补充一些 self.level = level obj=Teacher('张三',18,123,456) print(obj.__dict__)#{'name': '张三', 'age': 18, 'gender': 123, 'level': 456}
在类中追加功能,但是不能追加'jason' class MyClass(list): def append(self,value): if value == 'jason' print('jason不能追加') return super().append(value) obj=MyClass() obj.append(11) obj.append(22) obj.append('jason') obj.append(33) print(obj)#jason不能追加 [11,22,33]
作业
1.整理今日内容及博客 2.练习ATM购物车准备考核