返回介绍

01. Python 工具

02. Python 基础

03. Numpy

04. Scipy

05. Python 进阶

06. Matplotlib

07. 使用其他语言进行扩展

08. 面向对象编程

09. Theano 基础

10. 有趣的第三方模块

11. 有用的工具

12. Pandas

接口

发布于 2022-09-03 20:46:15 字数 7562 浏览 0 评论 0 收藏 0

Python 中,鸭子类型(duck typing)是一种动态类型的风格。所谓鸭子类型,来自于 James Whitcomb Riley 的“鸭子测试”:

当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。

假设我们需要定义一个函数,这个函数使用一个类型为鸭子的参数,并调用它的走和叫方法。

在鸭子类型的语言中,这样的函数可以接受任何类型的对象,只要这个对象实现了走和叫的方法,否则就引发一个运行时错误。换句话说,任何拥有走和叫方法的参数都是合法的。

先看一个例子,父类:

In [1]:

class Leaf(object):
    def __init__(self, color="green"):
        self.color = color
    def fall(self):
        print "Splat!"

子类:

In [2]:

class MapleLeaf(Leaf):
    def fall(self):
        self.color = 'brown'
        super(MapleLeaf, self).fall()

新的类:

In [3]:

class Acorn(object):
    def fall(self):
        print "Plunk!"

这三个类都实现了 fall() 方法,因此可以这样使用:

In [4]:

objects = [Leaf(), MapleLeaf(), Acorn()]

for obj in objects:
    obj.fall()
Splat!
Splat!
Plunk!

这里 fall() 方法就一种鸭子类型的体现。

不仅方法可以用鸭子类型,属性也可以:

In [5]:

import numpy as np
from scipy.ndimage.measurements import label

class Forest(object):
    """ Forest can grow trees which eventually die."""
    def __init__(self, size=(150,150), p_sapling=0.0025):
        self.size = size
        self.trees = np.zeros(self.size, dtype=bool)
        self.p_sapling = p_sapling

    def __repr__(self):
        my_repr = "{}(size={})".format(self.__class__.__name__, self.size)
        return my_repr

    def __str__(self):
        return self.__class__.__name__

    @property
    def num_cells(self):
        """Number of cells available for growing trees"""
        return np.prod(self.size)

    @property
    def losses(self):
        return np.zeros(self.size)

    @property
    def tree_fraction(self):
        """
 Fraction of trees
 """
        num_trees = self.trees.sum()
        return float(num_trees) / self.num_cells

    def _rand_bool(self, p):
        """
 Random boolean distributed according to p, less than p will be True
 """
        return np.random.uniform(size=self.trees.shape) < p

    def grow_trees(self):
        """
 Growing trees.
 """
        growth_sites = self._rand_bool(self.p_sapling)
        self.trees[growth_sites] = True    

    def advance_one_step(self):
        """
 Advance one step
 """
        self.grow_trees()

class BurnableForest(Forest):
    """
 Burnable forest support fires
 """    
    def __init__(self, p_lightning=5.0e-6, **kwargs):
        super(BurnableForest, self).__init__(**kwargs)
        self.p_lightning = p_lightning        
        self.fires = np.zeros((self.size), dtype=bool)

    def advance_one_step(self):
        """
 Advance one step
 """
        super(BurnableForest, self).advance_one_step()
        self.start_fires()
        self.burn_trees()

    @property
    def losses(self):
        return self.fires

    @property
    def fire_fraction(self):
        """
 Fraction of fires
 """
        num_fires = self.fires.sum()
        return float(num_fires) / self.num_cells

    def start_fires(self):
        """
 Start of fire.
 """
        lightning_strikes = (self._rand_bool(self.p_lightning) & 
            self.trees)
        self.fires[lightning_strikes] = True

    def burn_trees(self):    
        pass

class SlowBurnForest(BurnableForest):
    def burn_trees(self):
        """
 Burn trees.
 """
        fires = np.zeros((self.size[0] + 2, self.size[1] + 2), dtype=bool)
        fires[1:-1, 1:-1] = self.fires
        north = fires[:-2, 1:-1]
        south = fires[2:, 1:-1]
        east = fires[1:-1, :-2]
        west = fires[1:-1, 2:]
        new_fires = (north | south | east | west) & self.trees
        self.trees[self.fires] = False
        self.fires = new_fires

class InstantBurnForest(BurnableForest):
    def burn_trees(self):
        # 起火点
        strikes = self.fires
        # 找到连通区域
        groves, num_groves = label(self.trees)
        fires = set(groves[strikes])
        self.fires.fill(False)
        # 将与着火点相连的区域都烧掉
        for fire in fires:
            self.fires[groves == fire] = True
        self.trees[self.fires] = False
        self.fires.fill(False)

测试:

In [6]:

forest = Forest()
b_forest = BurnableForest()
sb_forest = SlowBurnForest()
ib_forest = InstantBurnForest()

forests = [forest, b_forest, sb_forest, ib_forest]

losses_history = []

for i in xrange(1500):
    for fst in forests:
        fst.advance_one_step()
    losses_history.append(tuple(fst.losses.sum() for fst in forests))

显示结果:

In [7]:

import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(10,6))

plt.plot(losses_history)
plt.legend([f.__str__() for f in forests])

plt.show()

https://www.wenjiangs.com/wp-content/uploads/2022/docimg20/Ej0sy4wx3mYpj5B6-fjB7eq.png alt="">

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文