内容概要
- 动静态方法
- 面向对象之继承的概念
- 继承的本质
- 名字的查找顺序
- 经典类与新式类
- 派生方法
动静态方法
class A1:
name = '牛'
def func1(self):
print('我是F1,看我牛不', self)
@classmethod
def func2(cls):
print('我是F2,看我牛不',cls)
@staticmethod
def func3(a):
print('我是F3,看我牛不',a)
1.类中直接定义函数 默认是绑定给对象的 类调用有几个参数传几个参数,对象调用第一个参数直接传对象本身,剩余参数有多少传多少
obj = A1()
obj.func1() # 对象调用F1 输出 我是F1,看我牛不 <__main__.A1 object at 0x0000021A65C48220>
A1.func1('这是啥') # 类调用F1 输出 我是F1,看我牛不 这是啥 (如果不传输参数就会报错!因为默认需要传obj进入函数)
2.被@classmethod 修饰的函数,默认绑定给类 类调用第一个参数就是类本身,对象也可以调用,并且将产生这个对象的类当作第一参数传入
obj.func2() # 我是F2,看我牛不 <class '__main__.A1'>
A1.func2() # 我是F2,看我牛不 <class '__main__.A1'>
3.被@staticmethod 修饰的函数,就变成普通的函数,无论是对象还是类去调用,有参数的情况下,都需要手动传参!
obj.func3('a') # 我是F3,看我牛不 a
A1.func3('a') # 我是F3,看我牛不 a
面向对象之继承
'''大家常说面向对象有三大特性
1.封装
2.继承
3.多态
三者中只有继承是核心(实操体验感最强)
封装和多态都是理论居多,并且略微有些抽象
'''
1.继承的含义
在现实生活中继承表示着人与人之间资源的从属关系
# 儿子继承父亲
在变成中继承表示类与类之间资源的丛书关系
# 类A(类B) 就表示了类A继承类B
2.继承的目的
比如在现实生活中儿子继承父亲的财产,儿子就支配了父亲的财产
那么在编程里面,类A继承类B,就可以让类A拥有类B的所有数据和方法的使用权限
3.继承的实操
class Son(Father):
pass
我们在类名()中填写类名 就表示这个类继承了()内的类
在python中支持多继承,括号内填写多个类名彼此根据逗号隔开即可
class Son(Father1,Father2,Father3):
pass
'''那么我们称继承其他类的类为:子类、派生类'''
'''被继承的类我们成为:父类、基类、超类'''
继承的本质
继承的本质其实也是为了节省代码
对象:数据与功能的结合体
类(子类):多个对象相同数据和功能的结合体
类(父类):多个类(子类)相同数据和功能的结合体
继承的本质应该分为两部分:
1.抽象
# 将多个类(子类)相同的部分抽出去形成一个新的类(父类)
2.继承
# 将多个类(子类)继承刚刚抽取出来的新的类(父类)
继承中的名称查找顺序
1.不继承的情况下,名字的查找顺序
class Father:
name = '我是大哥'
def func(self):
print('from func')
print(Father.name) # 我是大哥 类直接调用公共的数据没有问题
obj1 = Father()
print(obj1.name) # 我是大哥 因为类中并没有直接定义对象的数据(属性),所以对象obj1名称空间中没有name,所以对象调用的还是类中的公共数据
obj1.name = '我是小弟' # 我们现在给对象obj1里添加了数据name = '我是小弟'
print(obj1.name) # 所以我们再次调用obj1.name的时候寻找的就是对象名称空间的name 它并不是公共的name
# 我们可以的出来一个结论 就是 对象是先从自己的名称空间中寻找.name 如果没有找到会去类的名称空间中寻找 name 找到了就返回 找不到就会报错
"""
对象查找名字的顺序
1.先从自己的名称空间中查找
2.自己没有再去产生该对象的类中查找
3.如果类中也没有 那么直接报错
对象自身 >>>> 产生对象的类
"""
2.单继承情况下的名称的查找顺序
class Father1:
name = '老王'
pass
class Son1(Father1):
name = '小明'
pass
obj1 = Son1() # 通过子类son1 生成一个对象
# 我们通过obj1 子类的对象调用name
print(obj1.name) # 小明
obj2 = Father1() # 同过父类 Father 生成一个对象
# 我们通过obj2 父类的对象调用name
print(obj2.name) # 老王
# 当我们将子类的name 注释掉后
print(obj1.name) # 老王 'Son1' object has no attribute 'name'
class B:
def func1(self):
print('我是牛')
def func2(self):
print('我是鸡')
class A(B):
def func1(self):
print('我是羊')
obj1 = A()
obj1.func2() # 我是鸡
'''单继承情况下的名称空间查找顺序其实与上述差不多'''
'''对象自身>>>>>产生对象的类>>>>>>父类'''
强调:对象点名字 永远从对象自身开始一步步查找
在看到self.名字的时候 一定要搞清楚self指代的是哪个对象
3.多继承情况下名称的查找顺序
菱形继承
广度优先(从左往右每条道路找完,最后才会找闭环的顶点)
非菱形继承
深度优先(从左往右每条路找完为止)
ps:mro()方法可以直接获取类名字的查找顺序
经典类、新式类
"""
经典类:不继承object或者其子类的类
新式类:继承object或者其子类的类
在python2中有经典类和新式类
在python3中只有新式类(所有类默认都继承object)
"""
class A(object):
pass
ps:以后我们在定义类的时候 为了兼容性考虑,如果没有其他明确的父类 也习惯写object,
派生方法
派生方法就是子类基于父类某个方法做了扩展
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Student(Person):
def __init__(self, name, age, gender, sid):
super().__init__(name, age, gender) # 子类调用父类的方法
# super(父类,self)
self.sid = sid
class Teacher(Person):
def __init__(self, name, age, gender, level):
super().__init__(name, age, gender)
self.level = level
stu1 = Student('jason', 18, 'male', 666)
print(stu1.__dict__)
tea1 = Teacher('tony', 28, 'female', 99)
print(tea1.__dict__)
class MyList(list):
def append(self, values):
if values == 'xiaoming':
print('xiaoming不能尾部追加') # 这是在给append方法添加额外的功能
return
super().append(values)
obj = MyList()
print(obj, type(obj))
obj.append(111)
obj.append(222)
obj.append(333)
obj.append('jason')
print(obj)
标签:obj,name,派生,继承,self,面向对象,对象,print
From: https://www.cnblogs.com/ddsuifeng/p/16855490.html