python常用函数进阶(1)

在今天的QRNN替代LSTM的过程中, 为了能够将代码改写成Tacotron2中模块类的形式,以便于将QRNN嵌入进现有代码, 学习了几种python函数和进阶用法:

  1. __call__() 函数
  2. lambda 函数
  3. np.random.randint() 函数
  4. @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中用前置下划线代表私有变量

posted @ 2019-07-23 15:46  JeffreyLee  阅读(161)  评论(0编辑  收藏  举报