python 高级重写继承总结

本文总结了Python中的继承特性,包括子类如何继承父类的构造方法、如何调用父类方法,以及方法重写。介绍了super()的使用,并探讨了静态方法和类方法的作用及使用场景。

继承总结:

1.子类在继承父类时,默认继承了父类的 __init__()方法,如果子类没有重写__init__方法,则在创建对象时默认调用父类的该方法。但如果重写了__init__ 时,实例化子类时,就不会调用父类已经定义的 __init_

 2.因为子类默认继承了父类的构造方法,所以子类可以不需要重写__init__()方法。如果子类重写了自己的__init__()方法,那么子类该方法的参数个数要大于等于父类的个数(要包含父类的参数)。否则,报错。因为python中一个类中只能有一个init方法,不支持构造方法的重载。

  3.注意:可以用super().的形式调用父类的构造方法,但这个时候参数不用写self了,注意跟直接用父类名.形式调用的区别。

  4.子类继承了父类所有的属性,包扣私有属性,只是私有属性不能直接去调用,而是要通过get/set方法进行调用。

  5.子类继承了父类的所有方法,同样 私有方法不能外部直接调用。 

   6.同样如果父类还有父类,那么子类也会继承父类的父类所有方法和属性(注意私有属性和 方法同样访问不了)

一、 方法重写

当父类中的方法不符合我们的需求时,可以通过重写,实现我们的需求

方法重写后,默认调用子类的方法

1. 方法重写

class Foo(object):  

        def __init__(self):    

   self.name = 'Foo'    

        def hi(self):        

                       print('hi,Foo')    

class Foo2(Foo):  

           def hi(self):        

                print('hi,Foo2')

if __name__ == '__main__':  

           f = Foo2()  

            f.hi()    #默认调用子类方法

调用父类的——属性

同调用父类的普通方法一样

class Foo(object):

  def __init__(self): 

 self.name = 'Foo'     

def hi(self):        

print('hi,Foo')

class Foo2(Foo):    

def __init__(self):      

 #Foo.__init__(self)  #方法1:在重写的方法内强制调用 父类名.父类方法名() 如果需要参数,则需要传参        

#super(Foo2,self).__init__()   #方法2: super(子类名,子类对象).父类方法() 如果需要参数,则需要传参      

 super().__init__()       

def hi(self):      

 print('hi,Foo2')

if __name__ == '__main__':  

 f = Foo2()  

 f.hi()    #调用父类方法  

 print(f.name)

静态方法

静态方法是一类特殊的方法,有时你可能需要写一个属于这个类的方法,但是这些代码完全不会使用到实例对象本身,例如:

 

class Pizza(object):
  @staticmethod
  def mix_ingredients(x, y):
    return x + y

  def cook(self):
    return self.mix_ingredients(self.cheese, self.vegetables)1234567

这个例子中,如果把mix_ingredients作为非静态方法同样可以运行,但是它要提供self参数,而这个参数在方法中根本不会被使用到。这里的@staticmethod装饰器可以给我们带来一些好处: 
    Python不再需要为Pizza对象实例初始化一个绑定方法,绑定方法同样是对象,但是创建他们需要成本,而静态方法就可以避免这些。

 

>>> Pizza().cook is Pizza().cook
False
>>> Pizza().mix_ingredients is Pizza.mix_ingredients
True
>>> Pizza().mix_ingredients is Pizza().mix_ingredients
True123456

可读性更好的代码,看到@staticmethod我们就知道这个方法并不需要依赖对象本身的状态。
可以在子类中被覆盖,如果是把mix_ingredients作为模块的顶层函数,那么继承自Pizza的子类就没法改变pizza的mix_ingredients了如果不覆盖cook的话。

类方法

什么是类方法呢?类方法不是绑定到对象上,而是绑定在类上的方法。

 

>>> class Pizza(object):
...   radius = 42
...   @classmethod
...   def get_radius(cls):
...     return cls.radius
... 
>>> 
>>> Pizza.get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza().get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza.get_radius is Pizza().get_radius
True
>>> Pizza.get_radius()
42123456789101112131415

无论你用哪种方式访问这个方法,它总是绑定到了这个类身上,它的第一个参数是这个类本身(记住:类也是对象)。 
什么时候使用这种方法呢?类方法通常在以下两种场景是非常有用的:


工厂方法:它用于创建类的实例,例如一些预处理。如果使用@staticmethod代替,那我们不得不硬编码Pizza类名在函数中,这使得任何继承Pizza的类都不能使用我们这个工厂方法给它自己用。

 


class Pizza(object):
  def __init__(self, ingredients):
    self.ingredients = ingredients

  @classmethod
  def from_fridge(cls, fridge):
    return cls(fridge.get_cheese() + fridge.get_vegetables())1234567


调用静态类:如果你把一个静态方法拆分成多个静态方法,除非你使用类方法,否则你还是得硬编码类名。使用这种方式声明方法,Pizza类名明永远都不会在被直接引用,继承和方法覆盖都可以完美的工作。

 


class Pizza(object):
  def __init__(self, radius, height):
    self.radius = radius
    self.height = height

  @staticmethod
  def compute_area(radius):
     return math.pi * (radius ** 2)

  @classmethod
  def compute_volume(cls, height, radius):
     return height * cls.compute_area(radius)

  def get_volume(self):
    return self.compute_volume(self.height, self.radius)
 

 

 

 

 

 

 

   

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值