码迷,mamicode.com
首页 > 编程语言 > 详细

Python 8th Day

时间:2016-07-01 19:57:27      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:

多态

我们编写一个名为 Animal 的 class, 有一个 run() 方法可以直接打印:

class Animal(object):
    def run(self):
        print(Animal is running...)

要理解多态的好处,我们还需要再编写一个函数,这个函数接受一个 Animal 类型的变量:

def run_twice(animal):
    animal.run()
    animal.run()

当我们传入Animal的实例时,run_twice()就打印出:

>>> run_twice(Animal())
Animal is running...
Animal is running...

如果我们再定义一个Tortoise类型,从 Animal 派生:

class Tortoise(Animal):
    def run(self):
        print(Tortoise is running slowly...)

当我们调用run_twice()时,传入Tortoise的实例:

>>> run_twice(Tortoise())
Tortoise is running slowly...
Tortoise is running slowly...

多态的好处就是,当我们需要传入 Tortoise 时,我们只需要接收 Animal 类型就可以了,因为 Tortoise 是 Animal 类型,然后,按照 Animal 类型进行操作即可。由于 Animal 类型有 run() 方法,因此,传入的任意类型,只要是 Animal 类或者子类,就会自动调用实际类型的 run() 方法,这就是多态的意思。

类成员

技术分享

普通字段(data attributes): Data attributes are pieces of data held by a specific instance of a class. 

静态字段(class attributes): Python also supports class attributes, which are variables owned by the class itself.

普通对象只能由对象访问,静态字段应该由类访问,静态字段在代码加载时已经创建。

普通方法 (instance method)

静态方法(static method)

与普通方法的不同:

1)去掉 self

2)使用 @staticmethod 装饰器

3)静态方法由类调用,其实就是函数,只是与这个类相关

类方法(class method)

类方法是一种特殊的静态方法,也由类调用,与静态方法不同:

1)自动传入一个 cls 参数,cls 为函数名

class Province:
    @classmethod
    def f2(cls):
        print(cls)

hn = Province(henan)
hn.f2()

输出为:<class ‘__main__.Province‘>

Class methods are methods that are not bound to an object, but to a class!

>>> 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()
42

对象名加 () 执行 __call__

类名加 () 执行 __init__ 

静态方法与类方法的对比

#!/usr/bin/env python

class Smoothie(object):

    YOGURT = 1
    STRAWBERRY = 2
    BANANA = 4
    MANGO = 8

    @staticmethod
    def blend(*mixes):
        return sum(mixes) / len(mixes)

    @staticmethod
    def eternal_sunshine():
        return Smoothie.blend(Smoothie.YOGURT, Smoothie.STRAWBERRY, Smoothie.BANANA)

    @staticmethod
    def mango_lassi():
        return Smoothie.blend(Smoothie.YOGURT, Smoothie.MANGO)

使用静态方法,需要 hardcode class 的名字,而使用类方法:

#!/usr/bin/env python

class Smoothie(object):

    YOGURT = 1
    STRAWBERRY = 2
    BANANA = 4
    MANGO = 8

    @staticmethod
    def blend(*mixes):
        return sum(mixes) / len(mixes)

    @classmethod
    def eternal_sunshine(cls):
        return cls.blend(cls.YOGURT, cls.STRAWBERRY, cls.BANANA)

    @classmethod
    def mango_lassi(cls):
        return cls.blend(cls.YOGURT, cls.MANGO)

合理使用类方法的第一个好处:当需要改类的名字时,类的方法不需要改动。

另一个好处就是,当我们再创建一个 subclass 时,

class BetterSmoothie(Smoothie):

    YOGURT = yogurt
    STRAWBERRY = strawberry
    BANANA = banana
    MANGO = mango

    @staticmethod
    def blend(*mixes):
        return , .join(mixes)

我们更新了静态方法 blend, 从 Smoothie 继承的类方法 eternal_sunshine() 和 mango_lassi() 会自动使用新的 blend 方法

属性:

class Pager:
    def __init__(self, all_count):
        self.all_count = all_count

    @property
    def all_pager(self):
        a1, a2 = divmod(self.all_count, 10)
        if a2 == 0:
            return a1
        else:
            return a1 + 1

    @all_pager.setter
    def all_pager(self, value):
        print(value)

    @all_pager.deleter
    def all_pager(self):
        print(del all_pager)

对一个普通方法使用装饰器 @property 就相当于构造了一个动态字段,构造的属性只能取值,不能赋值,除非使用 @func_name.setter 装饰器再构造一个函数,使用 @func_name.deleter 装饰器使属性可删除,这样属性就具有完整的字段属性。

一个例子:

class Celsius:
    def __init__(self, temperature = 0):
        self.set_temperature(temperature)

    def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32

    # new update
    def get_temperature(self):
        return self._temperature

    def set_temperature(self, value):
        if value < -273:
            raise ValueError("Temperature below -273 is not possible")
        self._temperature = value

在 instance variable 前加一个 ‘_’ 意思是指明该字段应为私有字段,但是从外部依然可以访问。

class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    def get_temperature(self):
        print("Getting value")
        return self._temperature

    def set_temperature(self, value):
        if value < -273:
            raise ValueError("Temperature below -273 is not possible")
        print("Setting value")
        self._temperature = value

    temperature = property(fget=get_temperature, fset=set_temperature)

最后一行的意思是,property attaches some code (get_temperature and set_temperature) to the member attribute accesses (temperature). 当试图获取对象的 temperature 字段时会自动执行 get_temperature 方法 instead of a dictionary (__dict__) look-up.

Super 方法

class C1:

    def f1(self):
        # print(‘c1.f1‘)
        return 123


class C2(C1):

    def f1(self):
        # 主动执行 C2 的父类的 f1 方法
        # super(C2,self) 相当于实例化了 C1 class
        ret = super(C2,self).f1()
        print(c2.f1)
        return ret

super 方法可以主动执行父类的同名方法。

 

Python 8th Day

标签:

原文地址:http://www.cnblogs.com/garyang/p/5623391.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!