在今天的QRNN替代LSTM的过程中, 为了能够将代码改写成Tacotron2中模块类的形式,以便于将QRNN嵌入进现有代码, 学习了几种python函数和进阶用法:
- __call__() 函数
- lambda 函数
- np.random.randint() 函数
- @property
1. __call__() 函数
首先直接看代一组代码:
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中称之为方法
,其作用在于给类的实例提供可调用的接口,即除了类本身是个可调用对象之外,类的实例也是一个可调用对象。
上面说明书式的定义不好理解,以例子为说明:
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的shape
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中用前置下划线代表私有变量