python經常使用函數進階(1)

在今天的QRNN替代LSTM的過程當中, 爲了可以將代碼改寫成Tacotron2中模塊類的形式,以便於將QRNN嵌入進現有代碼, 學習了幾種python函數和進階用法:

  1. __call__() 函數
  2. lambda 函數
  3. np.random.randint() 函數
  4. @property



1. __call__() 函數

首先直接看代一組代碼:python

class test1():
    def __init__(self, a):
        self.a = a
    def __call__(self, b):
        self.b = b
        print(self.b)
        return (self.a + self.b)

n1 = test1(1)
print(hasattr(n1, '__call__'))
>>>True

class test2():
    def __init__(self, a):
        self.a = a

n2 = test2(2)
print(hasattr(n2, '__call__'))
>>>False

上面代碼中定義了兩個類,分別是test1類和test2類,不一樣的是,test1類中多定義了一個__call__()函數。分別實例化這兩個類,而後採用hasattr()函數查看兩個實例對象,就能夠總結出如下__call__()函數的做用:
__call__()函數,或者在python中稱之爲方法,其做用在於給類的實例提供可調用的接口,即除了類自己是個可調用對象以外,類的實例也是一個可調用對象。
上面說明書式的定義很差理解,以例子爲說明:dom

n1 = test1(1)
value = n1(2)
print(value)
>>>3

上面代碼中n1是類test1的一個實例化對象,有了__call__()函數,就能夠像初始化類的實例那樣,寫出第二行那樣的代碼。更爲通俗的說,就是咱們實際想要寫的操做函數,均可以放到__call__()函數的內部中進行,這樣就可讓類的實例做爲普通python函數那樣使用。實際上,就能夠理解成是一種()運算符的重載。函數


2. lambda 函數

g = lambda x:x+1    # (1)

def g(x):           # (2)
    return x+1

上面代碼(1)徹底等同於(2),代碼精簡,實際效率不會有改變學習


3. np.random.randint() 函數

import numpy as np

# np.random.randint(low, high, size)

np.random.randint(1,3,size = [1,3])
>>>[[1],[2],[2]]

該函數產生[low, high)之間的隨機整數,格式爲指定size的shapecode


4. @property

# 原始版本
class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature

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

# 普通添加限制版本
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

# property版本
class Celsius:
    def __init__(self, temperature = 0):
        self._temperature = temperature

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

    @property
    def temperature(self):
        print("Getting value")
        return self._temperature

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

@property的產生來源於現實須要,原始版本的Celsius在建立實例時,沒法給出溫度的限制區間。若是直接經過添加get()函數和set()函數的方法來設定限制,那麼在訪問實例的屬性的時候,代碼已經變成沒法向後兼容了。所以,爲了兼顧向後兼容性和設定限制,@property應運而生。
實際上,觀察@property的代碼,能夠發現溫度已經從公有屬性,變成私有屬性,也就是說,爲了向後兼容性,@property提供了訪問私有屬性的接口。對象

Tips : An underscore (_) at the beginning is used to denote private variables in Python.
python中用前置下劃線表明私有變量接口

相關文章
相關標籤/搜索