Python 8th Day

多态

我们编写一个名为 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 方法可以主动执行父类的同名方法。

时间: 2024-10-07 11:11:01

Python 8th Day的相关文章

python小技巧(转)

http://blog.jobbole.com/63320/ 30 Python Language Features and Tricks You May Not Know About Posted on Mar 05, 2014 , last modified on May 19, 2014 - Permanent link 1   Introduction Since I started learning Python, I decided to maintain an often visi

Retrieving Out Params From a Stored Procedure With Python

http://www.rodneyoliver.com/blog/2013/08/08/retrieving-out-params-from-a-stored-procedure-with-python/ AUG 8TH, 2013 I was hacking some python today which calls a stored procedure that sends back an out parameter to indicate whether or not it complet

Python for Data Analysis | MovieLens

Background MovieLens 1M数据集含有来自6000名用户对4000部电影的100万条评分数据. ratings.dat UserID::MovieID::Rating::Timestamp users.dat UserID::Gender::Age::Occupation::Zip-code movies.dat MovieID::Title::Genres 通过pandas.read_table将各个表分别读到一个pandas DataFrame对象中. * head=Non

Python实践练习:电话号码和 E-mail 地址提取程序

题目: 假设你有一个无聊的任务,要在一篇长的网页或文章中,找出所有电话号码和邮件地址.如果手动翻页,可能需要查找很长时间.如果有一个程序,可以在剪贴板的文本中查找电话号码和 E-mail 地址,那你就只要按一下 Ctrl-A 选择所有文本,按下 Ctrl-C 将它复制到剪贴板,然后运行你的程序.它会用找到的电话号码和 E-mail地址,替换掉剪贴板中的文本. 测试文本 Skip to main content Home Search form Search GO! Topics Arduino

《Python从入门到实践》--第五章 各种情形下使用if语句2 课后练习

题目: 5-8 以以特特殊殊方方式式跟跟管管理理员员打打招招呼呼 :创建一个至少包含5个用户名的列表,且其中一个用户名为'admin' .想象你要编写代码,在每位用户登录网站后都打印一条问候消息.遍历用户名列表,并向每位用户打印一条问候消息. 如果用户名为'admin' ,就打印一条特殊的问候消息,如“Hello admin, would you liketo seeastatus report?”.否则,打印一条普通的问候消息,如“Hello Eric, thank you for loggi

Python学习1-Python和Pycharm的下载与安装

本文主要介绍Python的下载安装和Python编辑器Pycharm的下载与安装. 一.Python的下载与安装 1.下载 到Python官网上下载Python的安装文件,进入网站后显示如下图: 网速访问慢的话可直接在这里下载:python-2.7.11.amd64 在Downloads中有对应的支持的平台,这里我们是在Windows平台下运行,所以点击Windows,出现如下: 在这里显示了Python更新的所有版本,其中最上面两行分别是Python2.X和Python3.X对应的最后更新版本

Python——深入理解urllib、urllib2及requests(requests不建议使用?)

深入理解urllib.urllib2及requests            python Python 是一种面向对象.解释型计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年,Python 源代码同样遵循 GPL(GNU General Public License)协议[1] .Python语法简洁而清晰,具有丰富和强大的类库. urllib and urllib2 区别 urllib和urllib2模块都做与请求URL相关的操作,但

python学习_day26_面向对象之封装

1.私有属性 (1)动态属性 在python中用双下划线开头的方式将属性隐藏起来.类中所有双下划线开头的名称,如__x都会自动变形成:_类名__x的形式.这种自动变形的特点是: a.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果.b.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的.c.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆

python面向对象知识点疏理

面向对象技术简介 类: 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例.class 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中且在函数体之外.类变量通常不作为实例变量使用. 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据. 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写. 实例变量:定义在方法中的变量,只作用于当前实例的类. 继承:即一个派生类(de