类和对象

1、Python中面向对象程序设计特点:封装、继承和多态

关于继承:可以打个形象的比方

矩形、菱形、平行四边形和梯形等都是四边形,以平行四边形为例,如果把平行四边形看成四边形的延伸,那么平行四边形就复用了四边形的属性和行为,同时添加了平行四边形特有的属性和行为,如平行四边形的对边平行且相等。

---->在Python中可以把平行四边形类看作是继承四边形类后产生的类,其中,将类似于平行四边形的的类称为子类,将类似于四边形的类称为父类或超类,

在阐释平行四边形和四边形关系时,可以说平行四边形是特殊的四边形,却不能说四边形是平行四边形。

---->同理Python中可以说子类的实例都是父类的实例,却不能说父类的实例都是子类的实例。

  • 继承中方法重写:指的是派生类方法想重写,不想从基类继承时,就需要改写基类的方法。

基类的成员都会被派生类继承,当基类中的某个方法不完全适用于派生类时,就需要在派生类中重写父类的这个方法。

 

class Fruit:           # 父类
    def harvest(self):
        pass
    
class Apple(Fruit):   # 派生类
    def harvest(self):    # 方法重写
        pass

 

  • 派生类中定义的__init__方法不会自动调用基类的__init__方法,如想让他调用,需要在派生类中加入super()__init__()
class Fruit:           # 父类
    def __init__(self,color = 'green'):
        Fruit.color = color
        print(Fruit.color)
    def harvest(self):
        print('水果原来是:'+ Fruit.color+ '的!')

class Apple(Fruit):   # 派生类
    def __init__(self):    # 方法重写
        print('i am apple')
        # super().__init__()
apple = Apple()
apple.harvest()

  

改写后:

class Fruit:           # 父类
    def __init__(self,color = 'green'):
        Fruit.color = color
        print(Fruit.color)
    def harvest(self):
        print('水果原来是:'+ Fruit.color+ '的!')

class Apple(Fruit):   # 派生类
    def __init__(self):    # 方法重写
        print('i am apple')
        super().__init__()
apple = Apple()
apple.harvest()

  

2、多态

3、创建类的同时会创建一个内置__init__方法,在内置函数中self参数是必要的,不可省略。

4、类属性和实例属性。通过在类中定义的变量(属性)位置不同,可分为类属性和实例属性。

  • 类属性:定义在类中的属性,该属性在类中函数体之外。
  • 实例属性:定义在类的方法之中的属性,只作用于当前实例之中。

访问方法:

类属性通过类名或实例名访问,而实例属性只能通过实例名访问。如果通过类名访问则会报错。

特殊点:实例属性可通过实例名称修改,并不影响该类其他实例中相应的实例属性的值。

(1)通过类名调用类属性:也可以通过实例名访问

class Geese:
    """雁类"""
    neck = "脖子太长"
    wing = "振翅频率高"
    leg = "腿位于身份的中心支点,行走自如"
    def __init__(self):
        print("我属于雁类,我有如下特征:")
        print(Geese.neck)
        print(Geese.wing)
        print(Geese.leg)

geese = Geese()

 

 输出如下:

我属于雁类,我有如下特征:
脖子太长
振翅频率高
腿位于身份的中心支点,行走自如

  

(2)只可通过实例名访问实例属性,

 

class Geese:
    """雁类"""
    def __init__(self):
        self.neck = "脖子太长"
        self.wing = "振翅频率高"
        self.leg = "腿位于身份的中心支点,行走自如"
        print("我属于雁类,我有如下特征:")
        print(self.neck)
        print(self.wing)
        print(self.leg)

geese = Geese()
geese1 = Geese()
geese1.neck = "我的实例属性值改变了"
print(geese1.neck)

  

结果如下:

我属于雁类,我有如下特征:
脖子太长
振翅频率高
腿位于身份的中心支点,行走自如
我属于雁类,我有如下特征:
脖子太长
振翅频率高
腿位于身份的中心支点,行走自如
我的实例属性值改变了

5、访问限制

三种形式: __foo__,__foo,_foo

  • __foo__:表示系统定义的方法名称:
  • _foo: protected(保护类型成员),只允许类本身和子类访问,不能使用(from module import *)导入
  • __foo: private(私有)类型成员。只允许定义该类本身访问,而不能通过类的实例访问,但可以通过类的实例名.类名__xxx方式访问
class Geese:
    """雁类"""
    _neck = "脖子太长"
    def __init__(self):
        print(Geese._neck)

geese = Geese()
print (geese._neck)  # 通过类的实例访问

  

 

 

class Geese:
"""雁类"""
__neck = "脖子太长"
def __init__(self):
print(Geese.__neck)

geese = Geese()
print(geese._Geese__neck)
print (geese.__neck) # 通过类的实例访问

 

  

可以看出__xxx定义的私有属性只能够通过类本身调用或类实例._类名__xxx的方式调用,直接用类实例调用就会报错。

 6、装饰器@property

作用简单理解为,写在函数前,将一个方法转换为属性,实现用于计算的属性,外部可以直接使用函数名来访问方法,不需要写成上述5中形式,且调用方法时不需要加()。另外需要注意通过此种方式创建的私有属性是只读的,外部也不可直接赋值修改,否则会报错。

承接上面的例子,私有属性无法在外部通过类访问时。也可以通过装饰器进行解决。

class Geese:
    """雁类"""
    def __init__(self,neck):
        self.__sh = neck
    # @property
    def show(self):
        return self.__sh
geese = Geese('脖子很长')
print(geese.show())
print(geese._Geese__sh)
print (geese.__sh)  # 通过类的实例访问

  

添加装饰器:

class Geese:
    """雁类"""
    def __init__(self,neck):
        self.__sh = neck
    @property
    def show(self):
        return self.__sh
geese = Geese('脖子很长')
print(geese.show)
print(geese._Geese__sh)
print (geese.__sh)  # 通过类的实例访问

  

 

外部修改私有属性:

class Geese:
    """雁类"""
    def __init__(self,neck):
        self.__sh = neck
    @property
    def show(self):
        return self.__sh
geese = Geese('脖子很长')
print(geese.show)
geese.show = '脖子不长'
print(geese.show)

  

 

 

 

 

 

posted @ 2019-08-19 07:39  Jude_h  阅读(197)  评论(0编辑  收藏  举报