JerryZH 发表于 2018-3-29 10:21:12

发现了一个问题,好像并没有初始化为0啊,都是在上一步的位置上移动的

jasonpy 发表于 2018-3-30 22:35:33

本帖最后由 jasonpy 于 2018-3-30 22:43 编辑

个人的一些学习心得,希望能帮助到看不懂的鱼友们

origin = (0, 0)         # 原点
legal_x = [-100, 100]   # x轴的移动范围
legal_y = [-100, 100]   # y轴的移动范围

def create(pos_x=0, pos_y=0):
# 初始化位于原点为主   
    def moving(direction, step):
    # direction参数设置方向,1为向右(向上),-1为向左(向下),0为不移动
    # step参数设置移动的距离
      nonlocal pos_x, pos_y #强制pos为非局部变量,可记录
      print('initial value pos_x: ',pos_x)
      print('initial valu pos_y: ',pos_y)
      new_x = pos_x + direction * step
      new_y = pos_y + direction * step
      # 检查移动后是否超出x轴边界
      if new_x < legal_x:
            pos_x = legal_x - (new_x - legal_x)
      elif new_x > legal_x:
            pos_x = legal_x - (new_x - legal_x)
      else:            
            pos_x = new_x
      # 检查移动后是否超出y轴边界
      if new_y < legal_y:
            pos_y = legal_y - (new_y - legal_y)
      elif new_y > legal_y:
            pos_y = legal_y - (new_y - legal_y)
      else:            
            pos_y = new_y
      print('final value pos_x: ',pos_x)
      print('final valu pos_y: ',pos_y)
      return pos_x, pos_y # return 这里是让moving这个function输出pos_x,pos_y
      #pos_x and pos_y are global virables, here specify nonlocal
    return moving
   
move = create() # move is a function type that returns the closure function//
# move(direction, step)
print('向右移动10步后,位置是:', move(, 10))
print('向上移动130步后,位置是:', move(, 130))
print('向左移动10步后,位置是:', move([-1, 0], 10))

# pos_x pos_y is not defined globally.....!!!

个人的一些研究,上面的代码加上几个注释后会输出以下,也就是说闭包很大的一个好处就是可以记住历史,这个用一般方程比较难做到。。
initial value pos_x:0
initial valu pos_y:0
final value pos_x:10
final valu pos_y:0
向右移动10步后,位置是: (10, 0)
initial value pos_x:10
initial valu pos_y:0
final value pos_x:10
final valu pos_y:70
向上移动130步后,位置是: (10, 70)
initial value pos_x:10
initial valu pos_y:70
final value pos_x:0
final valu pos_y:70
向左移动10步后,位置是: (0, 70)

我尝试了一下不用闭包写一段比较容易明白的代码:
origin = (0, 0)         # 原点
legal_x = [-100, 100]   # x轴的移动范围
legal_y = [-100, 100]   # y轴的移动范围

tempos_x = 0
tempos_y = 0

def moving(direction, step):
# direction参数设置方向,1为向右(向上),-1为向左(向下),0为不移动
# step参数设置移动的距离
    #nonlocal pos_x, pos_y #强制pos为非局部变量
    global tempos_x, tempos_y
    pos_x = tempos_x #设置起始值
    pos_y = tempos_y #设置起始值
   
    new_x = pos_x + direction * step
    new_y = pos_y + direction * step
    # 检查移动后是否超出x轴边界
    if new_x < legal_x:
      pos_x = legal_x - (new_x - legal_x)
    elif new_x > legal_x:
      pos_x = legal_x - (new_x - legal_x)
    else:            
      pos_x = new_x
    # 检查移动后是否超出y轴边界
    if new_y < legal_y:
      pos_y = legal_y - (new_y - legal_y)
    elif new_y > legal_y:
      pos_y = legal_y - (new_y - legal_y)
    else:            
      pos_y = new_y
    tempos_x = pos_x
    tempos_y = pos_y
    return pos_x, pos_y
    #pos_x and pos_y are global virables, here specify nonlocal
#return moving
   
#move = create() # move is a function type that returns the closure function//
# move(direction, step)
print('向右移动10步后,位置是:',moving(,10))
print('向上移动130步后,位置是:',moving(,130))
print('向左移动10步后,位置是:',moving([-1, 0],10))
# if use this function, then it can't remember pos_x and pos_y..
#..need to manually define the last positon to return the same results...

同样,这个会输出一样的结果:
向右移动10步后,位置是: (10, 0)
向上移动130步后,位置是: (10, 70)
向左移动10步后,位置是: (0, 70)

显而,第二段代码是比较“低级”的也更容易明白的,明白了后,就知道闭包的好处啦,就是可以非常简单的“记忆”,只需要定义一个“nonlocal”,就可以有记忆功能了,也不需要定义全局变量。希望这个可以帮助到看不懂的人

白昼 发表于 2018-4-1 12:39:24

66666666,赞一个

18166893221 发表于 2018-4-11 15:50:43

关于每次都会初始化的理解:
有两个关键知识点:
1.函数中的默认参数值:
当某些函数需要有默认输入(即提前设定好缺省值)可用以下格式:
def myfun(x=缺省值):
        print(x)
2.闭包函数(函数中的函数)的调用:
example:
def test1():
    def test2():
      print('sucessful')
    return test2()
def test1_1():
    def test2_2():
      print('bingo')
    return test2_2
如果需要访问test2以及test2_2,则分别输入test1()以及test1_1()()。
而此程序中,move=create(),相当于move已经调用了create(位置1)(位置2)的位置一,而且位置一使用了默认值(pos_x=0,pos_y=0),这样相当于通过move()这种操作把一个闭包函数脱掉了一层衣服。在需要调用的时候,只需要输入里面那层衣服需要的值就好。
如果要是type(move)的话可以发现其返回值是function类型。
当然也可以试试 test=create(2,2)(,1),这样也是有输出结果的。

wstczzh 发表于 2018-4-13 22:00:27

666

彩虹七号 发表于 2018-4-24 11:33:33

看不懂 ,长路漫漫呀

向日葵4444 发表于 2018-4-27 19:40:40

yu_wind 发表于 2014-1-11 16:22
请问
if new_x < legal_x:
            pos_x = legal_x - (new_x - legal_x)


等于的不算超出边界,在else里 就行

theendofen 发表于 2018-4-29 11:19:29

新手,,,,,看不懂。。。。。。

hbinn 发表于 2018-5-9 13:24:53

能复制否

STmove 发表于 2018-5-19 14:45:05

IDLE返回:SyntaxError: multiple statements found while compiling a single statement
查了下是说我在一行里写了多行的代码,是版本的问题么,我装的是3.4.1

zhdwinter 发表于 2018-5-22 21:35:14

guokai83524 发表于 2014-3-17 13:05
看不懂最后的调用30-33行,为什么move里面可以这样带参数,不理解

因为move = create()之后,move 就相当于将内部函数moving了

zhdwinter 发表于 2018-5-22 21:37:23

为什么每次动作完之后需要强制将pos_x和pos_y强制归零呢,为什么不能在上次位置的基础上进行移动呢

chengjun079 发表于 2018-5-23 09:41:43

ddddddddd

糖妖妖66 发表于 2018-5-28 14:46:59

yu_wind 发表于 2014-1-11 16:22
请问
if new_x < legal_x:
            pos_x = legal_x - (new_x - legal_x)


假设 pos_x等于legal_x 那么 if 里面 改写一下 变成pos_x+new_x = legal_x【0】+legal_x
因为pos_x等于legal_x 所以消掉那么久变成new_x = legal_x了如果 new_x= legal_x就不会进if了 应该进 else 毕竟你的if条件是 new_x < legal_x

akyl56 发表于 2018-5-31 11:18:21

小白要成神 发表于 2018-6-8 15:57:10

yu_wind 发表于 2014-1-11 16:55
我估计是我没看明白咋么移动的,
我的理解是, x轴上原来-80 往左挪30变成-110然后 if的结果是-90 ...

我觉得也是,撞完墙会退回来

tglovell 发表于 2018-6-10 23:30:34

想问一下:28行return moving没有看懂,moving不是一个变量,那返回的是什么呢,是将这个函数运行一遍吗。还有move到底是一个函数还是变量呢。move运行之后的返回结果moving到底是什么形式呢?

cable 发表于 2018-6-20 12:00:02

还没明白,学完20课再来学

www.4399whs 发表于 2018-6-21 01:10:54

小甲鱼哥哥能赠送一点鱼币吗,好想做课后习题却没有鱼币,内心十分纠结呢,下个月我就可以开会员了,这个月实在囊中羞涩

阿羚 发表于 2018-6-27 10:11:31

小甲鱼 发表于 2014-1-11 16:24
等于的话走else:分支,临界并不算超界

可是else:分支不是pos_x = new_x吗?为什么if new_x < legal_x时,不直接pox_x=legal_x呢?
页: 3 4 5 6 7 8 9 10 11 12 [13] 14 15 16 17 18 19 20 21 22
查看完整版本: 游戏中的角色移动:闭包(closure)在实际开发中的作用