python面向对象(2)
动态方法和静态方法
# 动态方法
	1.绑定给对象的方法
  	class Student:
      def run(self):
        print(self)
  	# 类调用绑定给对象的方法:有几个参数就需要传几个参数
    Student.run(123)
    # 对象调用绑定给对象的方法:会自动将对象当做第一个参数传入
    obj1.run()
	2.绑定给类的方法
    class Student:
      @classmethod
      def eat(cls):
        pr(cls)
  	# 类调用绑定给类的方法:会自动将类当做第一个参数传入
    print(Student)  # <class '__main__.Student'>
    Student.eat()  # <class '__main__.Student'>
    # 对象调用绑定给类的方法:也不需要传参 会将产生该对象的类自动当做第一个参数传入
    obj1.eat()  # <class '__main__.Student'>
    
    '''在类定义中,使用@classmethod装饰器修饰的方法,必须至少有一个参数,且第一个参数留给了cls,cls指代调用者即类对象自身
 cls这个标识符可以是任意合法名称,但是为了易读,请不要修改
 通过cls可以直接操作类的属性'''
# 动态方法
	class Student:
    	@staticmethod
      def speak(cls):
          print(cls)
	1.普普通通的函数:无论谁来调 都必须传固定的参数个数
    # 类调用静态方法:要自己传值
    Student.speak(123)
    # 对象调用静态方法:要自己传值
    obj1.speak(321)
    
面向对象的三大特性之一:继承
# 继承的概念:
子类 拥有 父类 的所有 方法 和 属性
# 继承的基本使用
	"""
		class A(B):  
			pass
	我们将被继承的类称为:父类或者基类     B
  继承别人的类称为:子类或者派生类			 A
	"""
    
# 在python中一个类可以同时继承多个父类
  	class A(B,C,D):
      pass
子类 继承自父类,可以直接享受 父类中已经封装好的方法,不需要再次开发
子类 中应该根据 职责,封装 子类特有的属性和方法
继承的本质
抽象:由下往上抽取相同特征
继承:由上往下直接白嫖资源
"""
在面向对象编程中 其实类和父类的主要功能都是用来减少代码冗余的
对象:数据与功能的结合体
类:多个对象相同数据和功能的结合体
父类:多个类相同数据和功能的结合体
"""
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
class Teacher(Person):
    def teach(self):
        print(f'{self.name}老师正在讲课')
class Student(Person):
    def study(self):
        print(f'{self.name}学生正在学习')
stu1 = Student('jason', 18, 'male')
#总结
class Student(Person)这种形式就是从父类继承,括号中写上继承的类的列表。
    继承可以让子类从父类获取特征(属性和方法)
  父类:
    calss Person就是Student和Teacher的父类,也称为基类,超类
  子类:
    Student就是Person的子类,也成为派生类
    
#在Python3中,object类是所有对象的根基类    
class A:
    pass
'如果类定义时,没有基类列表,等同于继承自object'
class A(object):
    pass
新式类和经典类
#新式类:
以 object 为基类的类,推荐使用
#经典类:
不以 object 为基类的类,不推荐使用
Python 3.x 
定义类时,如果没有指定父类,会 默认使用 object 作为该类的 基类 —— Python 3.x 中定义的类都是 新式类
Python 2.x 
定义类时,如果没有指定父类,则不会以 object 作为 基类
'''为了保证编写的代码能够同时在 Python 2.x 和 Python 3.x 运行!
今后在定义类时为了兼容,如果没有父类,建议统一继承自 object '''
查看继承的特殊属性和方法
class A:
    pass
print(A.__base__)               #类的基类。
print(A.__bases__)              #类的基类元组。
print(A.__mro__)                #显示方法查找顺序,基类的元组。
print(A.mro())                  #同上,返回列表。
print(A.__subclasses__())       #类的子类列表。
继承的优缺点
#继承的特点:
   a.子类的独享可以直接访问父类中未被私有化的属性,访问私有化属性时,需要在父类提供get和set方法
   b.子类对象可以调用父类中未被私有化的方法
   c.父类对象无法访问子类对象的属性和方法
#优缺点:
1.优点:
   可以简化代码,减少冗余
   可以提高代码的维护性
   可以提高代码的安全性
   继承是多态的前提
2.缺点:
耦合和内聚被用来描述类与类之间的关系,一般高内聚低耦合说明代码比较好
继承关系中耦合性相对较高【如果修改父类,则所有子类需求都会改变】
名字的查找顺序
不继承情况下
# 名字的查找顺序是
  	先从对象自己的名称空间中查找 没有则去类里面的名称空间查找
    	对象	>>>	类
        
  '''注意设置值的情况下是在自身的名称空间中添加或者修改数据'''
  
单继承情况下
#名字的查找顺序是
  	先从对象自己的名称空间中查找 没有择取产生对象的类中查找
    如果还没有并且类有父类则去父类中查找 以此往复下去!!!
    	对象	>>>	类	>>> 父类
# 代码示例:        
  	class A:
      def f1(self):
          print('from A.f1')
      def f2(self):
          print('from A.f2')
          self.f1()  '''以后看到self点东西 一定要问自己self是谁'''
    class MyClass(A):
       def f1(self):
            print('from MyClass.f1')
    obj = MyClass()
    obj.f2()
    # 执行的方法分别是A里面的f2和MyClass里面的f1
    
#查询顺序
  1.对象.属性 : 先从对象空间找,再从类名空间找,再从父类找
  2.类名.属性 : 先从类名空间找,再从父类找
  3.对象与对象之间是相互独立的
多继承情况下(了解)
'研究菱形和非菱形问题object不参与图形构建'     
  #非菱形继承的情况下
  	父类中名字的查找顺序就是按照继承时从左往右依次查找
   	如果多个父类还有分类 那么遵循"深度优先"
	eg:D->C->B->A
  #菱形继承的情况下
  	父类中名字的查找顺序就是按照继承时从左往右依次查找
   	如果多个父类还有分类 那么遵循"广度优先"
    D->B->C->A

派生类
# 派生的定义:
子类可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类)
重新定义了自己的属性且与父类重名那么调用新增的属性时 就以自己为准
#代码示例:
class Animal():
    def __init__(self,name,age,gender,birth):
        self.name = name
        self.age = age
        self.gender = gender
        self.birth = birth
class Cat(Animal):
    def __init__(self,name,age,gender,birth,eat,live):
        # 子类调用父类的方法
        super().__init__(name,age,gender,birth) 
         # 自己还要添加一个额外的东西
        self.eat = eat
        self.live = live
class Dog(Animal):
    def __init__(self,name,age,gender,birth,play,sleep):
        super().__init__(name,age,gender,birth)
        self.play = play
        self.sleep = sleep
        """
如果自己写的子类需要使用父类的方法 并且还需要基于该方法做扩展
这样的子类我们称之为派生类(本质还是子类)      
    那么可以使用super关键字来实现
"""
        
