GO进阶训练营

138 阅读4分钟

download:GO进阶训练营

Q:参加 Go 进阶训练营,需要具备什么基础?
需要掌握 Go 语言基础语法,并具备一定的 Go 语言相关项目开发经验。

Q:学完课程后能到什么水平?
Go 进阶训练营课程设计对标字节跳动 2-2 级胜任力模型,教学贴近大厂真实场景。课程中的实践驱动,不仅可以系统提升你的代码硬实力,同时也会培养你进入一线互联网大厂必备的思维能力。
我们的课程培养目标是大厂的资深 Go 工程师、高级 Go 开发工程师、Go 技术专家。按照老师系统性的规划,用心学习,可以帮你摆脱低效和痛苦的自学,事半功倍,学完后可以达到一线互联网大厂中高级 Go 开发工程师的水平。

哪些人适合报名 Go 进阶训练营?

2 年以上工作经验,在理论和技术方面有进阶学习需求的 Go 语言工程师;
其它语言转 Go(比如 Java )的工程师,用 Go 写过简单的项目,但工作中用 Go 写中大型的复杂项目比较吃力。
天都会增加新价格,因此平均值要考虑至目前为止所有的价格。

>>>avg(10)
10.0
>>>avg(20)
15.0
>>>avg(30)
20.0
2、实现方式1:使用类实现

class Averager():

def __init__(self):
    self.series = []

def __call__(self, new_value):
    self.series.append(new_value)
    total = sum(self.series)
    return total/len(self.series)

avg = Averager()

print(avg(10)) #10.0
print(avg(20)) #15.0
print(avg(30)) #20.0
函数说明:

1、定义一个类变量保存价格,avg = Averager() 类的实例化,生成实例对象时,创建self.series,是一个数组。

2、call 魔法方法:使得 Averager类的 avg 实例对象变成了可调用对象。

3、每次调用 avg(arg) 时,类变量的列表都增加一个 arg 的元素,返回 列表总和的平均值。

3、实现方式2:使用高阶函数实现(把函数作为参数传入,这样的函数称为高阶函数)

def make_averager():
series = []

def averager(new_value):
    series.append(new_value)
    total = sum(series)
    return total/len(series)

return averager

avg = make_averager()
print(avg.code.co_varnames) #('new_value', 'total')
print(avg.code.co_freevars) #('series',)
print(avg(10)) #10.0
print(avg(20)) #15.0
print(avg(30)) #20.0

print(avg.closure) #(<cell at 0x00000151B2C415E8: list object at 0x00000151B2DA7AC8>,)
print(avg.closure[0].cell_contents) #[10, 20, 30]
函数说明:

调用 make_averager() 时,返回一个 averager 函数对象。每次调用 averager 时,它会把参数添加到系列值中,然后计算平均值。

series 是 make_averager 函数的局部变量

4、方法1和方法2的相通之处和不同之处

相通:

调用 Averager() 或 make_averager() 都得到一个可调用对象 avg,它会更新历史值,然后计算当前均值。

我们只需要调用 avg(n) ,把n放入到系列值中,然后重新计算均值。

不同:

Averager 类的实例 avg 在 self.series 中存储历史值;

make_averager 函数在哪里寻找 series ?series 是 make_averager 函数的局部变量,因为那个函数的定义体中初始化了series, series = [] 。可是调用avg(10)时,make_averager 函数已经返回了,它的本地作用域也一去不复返了。

三、闭包和自由变量
1、闭包和自由变量:在实现方式2的基础上

整个部分称为闭包

series = []

def averager(new_value):
    series.append(new_value) # series 称为自由变量
    total = sum(series)
    return total/len(series)

说明:

averager 的闭包延伸到那个函数的作用域之外,包含自由变量的绑定。

2、func.code
print(avg.code.co_varnames) #('new_value', 'total') 将函数参数和局部变量以元组的形式返回

print(avg.code.co_freevars) #('series',) 返回内部函数中引用外部函数参数,即自由变量(通过函数闭包引用)

更详细的说明参考:

blog.csdn.net/jpch89/arti…

3、func.closure

示例2中

print(avg.closure) #(<cell at 0x00000151B2C415E8: list object at 0x00000151B2DA7AC8>,)
print(avg.closure[0].cell_contents) #[10, 20, 30]

或者遍历得到:
[cell.cell_contents for cell in func.closure]
说明:

Python 3 已将名为func_X 的函数属性重命名为使用 X 形式,从而在函数属性名称空间中为用户定义的属性释放了这些名称。

例如,func_closure,func_code,func_defaults,func_dict,func_doc,func_globals,func_name
分别重命名为closurecodedefaultsdictdocglobalsname

其实闭包函数相对于普通函数会多出一个closure的属性,里面定义了一个元组用于存放所有的cell对象,每个cell对象一一保存了这个闭包中所有的外部变量。

data model将closure定义为:None或包含该函数的自由变量绑定的单元格元组。

如果closure不是None,它将创建一个字典,将code.co_freevars中的每个单元格名称映射到元组中的相应cell.cell_contents。

“Cell”对象用于实现由多个作用域引用的变量。

对于每个这样的变量,一个“Cell”对象