鱼C论坛

 找回密码
 立即注册
查看: 6216|回复: 19

请教,为什么这个递归不用return?

[复制链接]
发表于 2015-10-7 01:34:19 | 显示全部楼层 |阅读模式
30鱼币
本帖最后由 1245722417 于 2015-10-7 01:40 编辑

研究第30课的一道作业题的答案好久。。
2. 编写一个程序,用户输入文件名以及开始搜索的路径,搜索该文件是否存在。如遇到文件夹,则进入文件夹继续搜索:
  1. import os

  2. def search_file(start_dir, target) :
  3.     os.chdir(start_dir)
  4.    
  5.     for each_file in os.listdir(os.curdir) :
  6.         if each_file == target :
  7.             print(os.getcwd() + os.sep + each_file) # 使用os.sep是程序更标准
  8.         if os.path.isdir(each_file) :
  9.             search_file(each_file, target) # 递归调用
  10.             os.chdir(os.pardir) # 递归调用后切记返回上一层目录

  11. start_dir = input('请输入待查找的初始目录:')
  12. target = input('请输入需要查找的目标文件:')
  13. search_file(start_dir, target)
复制代码


1. 这个递归函数没有使用return,为什么?看到有同学说递归需要通过return语句实现自己调用自己的过程。。。
2.  我猜os.chdir(os.pardir) 这句话应该是这个递归的退出机制了,但是到底是怎么起作用的实在想不明白,为什么只用返回上一级目录?与它父级的循环有什么相互关系呢?最终函数是依据什么判断才终止递归行为的?
3. 另外,我还手贱尝试了把os.chdir(os.pardir) 这句话注释掉,并且给search_file(each_file, target) 前面加上return看看会发生什么。。。又是各种匪夷所思。。。只会搜到一个结果不说(如果存在多个相同文件名的话)这个时候试图修改路径是不允许的,而如果去掉return,很有可能就会搜出多个相同结果,尽管相同路径只会有一个唯一名字的文件。。这些现象搞得我不明就里。。在此求指点。。。

最佳答案

查看完整内容

问题1:递归不是需要调用return才会递归,return 是函数又返回值(返回值可以是数字,字符串,列表,字典,实例对象等等)例如:无返回值的递归(以汉诺塔为例) 会发现print最后显示的为None,即函数没有返回值(也不准确,因为返回了一个None,你可以这么理解,就是没有return,函数里面都是一条条的执行语句,这些执行语句只不过在这个函数里而已,函数调用了,它就自然而然按顺序来执行,并没有给这个函数(面向对象编程实例 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-7 01:34:20 | 显示全部楼层
问题1:递归不是需要调用return才会递归,return 是函数又返回值(返回值可以是数字,字符串,列表,字典,实例对象等等)例如:无返回值的递归(以汉诺塔为例)
  1. def hanota(n,x='x',y='y',z='z'):
  2.     if n == 1:
  3.         print(x,'-->',z)
  4.     else:
  5.         hanota(n-1,x,z,y)#将前n-1个盘子从x移到y上
  6.         print(x,'-->',z)#将底下的最后一个盘子从x移到z
  7.         hanota(n-1,y,x,z)#将y的n-1个盘子移到z上
  8. print(hanota(2))
复制代码

会发现print最后显示的为None,即函数没有返回值(也不准确,因为返回了一个None,你可以这么理解,就是没有return,函数里面都是一条条的执行语句,这些执行语句只不过在这个函数里而已,函数调用了,它就自然而然按顺序来执行,并没有给这个函数(面向对象编程实例的属性等)贴一个标签,给它一个帽子或者数值对象什么的,只是执行而已。至于shell里面显示的内容,只是执行语句print(x,'-->',z)的显示,而不是函数hanota(2)的值得显示。
我们来看一个又返回值的写一个简单的阶乘例子
  1. def jiecheng(n):
  2.     if n == 0:
  3.         return 1
  4.     if n < 0:
  5.         raise ValueError('卧槽,负数没有阶乘,发散的额,你要用Gamma函数来定义么?!')
  6.     elif n > 0:
  7.         return n*jiecheng(n-1)
  8.     print('都return了,还会往下执行,打印这句么?')
复制代码

return返回一个值以后函数就不往下面执行了,后面的代码就都是无效的代码,所以print是不会执行的
  1. >>> jiecheng(5)
  2. 120
  3. >>> jiecheng(5)== 120
  4. True
复制代码

函数里并没有print(120)语句,那么这个120是怎么在shell里显示的,也就是jiecheng(5)的返回值是120。递归中return先介绍这么多吧,至于返回实例等你想不明白再解决,不然你的一下子问这么多问题,得打多少字啊!
问题2 os.chdir(os.pardir),只是返回上一层目录,递归语句10.search_file(each_file, target) # 递归调用
已经将for循环中的一个each_file(9. if os.path.isdir(each_file) :判断这个each_file是不是文件夹,因为文件夹是没有扩展名的,所以each_file文件夹时可以在当前目录下组成路径,那么if 就是True了。然后把这个each_file文件递归的寻找完),这个递归完才会再执行11的语句,必须得返回上一层目录了,然后进行下一轮的for循环,必须得返回上一层,不然程序会在上一个递归的each_file路径中重复寻找。
也就是问题3:你说的一个结果会打印很多次。
举个列吧:
比如我的F盘有两个文件夹,一个命名为:文件1,一个命名为:文件2,然后一个.txt的文档,命名:雾草.txt
然后文件1里面也有只有一个文件命名:雾草.txt,文件2为空文件。
提示输入“请输入待查找的初始目录:”我输入F:
请输入需要查找的目标文件:我输入:雾草.txt
我们来看程序流程:
04将F:更改为当前路径
06for循环找到3个文件(文件1,文件2,雾草.txt)
07each_file = 文件1 即!= target,然后执行09
09判断路径存在(文件1是一个文件路径当然会存在)
然后执行10(到了递归了search_file(each_file, target),然后执行03,这时实参是each_file, target,执行04,04将目录更改到F:/文件1,然后06语句for循环,for循环在路径F:/文件1,只找到1个文件(雾草.txt)
然后07执行发现if判断if each_file == target :为True,因而打印了路径,然后10执行完)
然后执行11,返回到上一路径F:
然后继续06的下一个for循环,这时each_file可能等于文件2,也可能等于 雾草.txt(这个得看os.listdir(os.curdir)返回的列表中文件的顺序),即若os.listdir(os.curdir) = ['文件1','雾草.txt','文件2'],那么
此时each_file = '雾草.txt',那么执行07,然后再06,此时each_file =  "文件2',找到0个,把F:路径以下的文件都找了一遍了,就结束了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-7 11:07:45 | 显示全部楼层
return就是函数一个返回语句,其实我觉得有时候拿他就当print用了
def a():
        return("I love fishC.com")
>>> a()
'I love fishC.com'


>>> def a():
        print("I love fishC.com")

       
>>> a()
I love fishC.com
递归是只要函数调用自身就是递归,上述代码中”search_file(each_file, target) # 递归调用“就已经是递归的调用了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-7 16:42:22 | 显示全部楼层
FDMa 发表于 2015-10-7 11:07
return就是函数一个返回语句,其实我觉得有时候拿他就当print用了
def a():
        return("I love fishC.com") ...

return和print毫无关系的,你的例子中a() = 'I love fishC.com',也就是函数a()的值是'I love fishC.com'的字符串,这样我们可以对a()进行字符串的一些列操作例如:
  1. >>> def a():
  2.         return("I love fishC.com")

  3. >>> a() == "I love fishC.com"
  4. True
  5. >>> a() == print("I love fishC.com")
  6. I love fishC.com
  7. False
  8. >>> a()[0]
  9. 'I'
  10. >>> a()[::-1]
  11. 'moc.Chsif evol I'
  12. >>>
复制代码


即对a()切片以及反转等等字符串的操作!!
可以看到a()和print('I love fishC.com')是不等的。
特别是后面学到类的时候,你这种思维会导致你更难理解类以及python的魔法方法。
其实你们课后题做到30课了很不错了,我只做到了27课(从课后题的回复痕迹可以看出),上午的时候花了10鱼币看了下楼主说的30课后作业。我是把小甲鱼的教程看到20多讲后停在那儿,抽着看,先把网易的英语python看完后,再把《像计算机科学家一样思考python》这本书给看完了!
关于return,我刚写了关于类的例子给你简单说下,顺便把后面41-45讲左右的魔法方法说下.
  1. class Aaa:
  2.     def __new__(cls,name,value):
  3.         print('nihao')
  4.         return Bbb(name,value)
  5.     def __init__(self,name,value):
  6.         self.name = name**2
  7.         self.value = value*2

  8. class Bbb:
  9.     def __new__(cls,name,value):
  10.         print('shnm')
  11.         return Ccc(name,value)
  12.     def __init__(self,fish,num):
  13.         self.fish = fish
  14.         self.num = num

  15. class Ccc:
  16.     def __init__(self,name,value):
  17.         self.name = [1,2,3,name]
  18.         self.value = value**3
  19.         self.pompt = '雾草'
  20.         self._woco = ''
  21.     def __len__(self):
  22.         print('11')
  23.         return len([1,2,3])
  24.     def __del__(self):
  25.         print('shanle')
  26.     def __str__(self):
  27.         print('beidiaoyong')
  28.         return str(self.name)
  29.     def __repr__(self):
  30.         return self.__str__()
  31.     def __getattr__(self,name):
  32.         print('buzai')
  33.         self.pompt = '被更新'

  34.     def __set__(self,instance,name):
  35.         print('set')
  36.         self._name = name.title()
  37.     def __get__(self,instance,owner):
  38.         print('quqiu')
  39.         return self._name
  40.     def __delete__(self,instance):
  41.         print(instance)

  42.     def __add__(self,other):
  43.         if type(other) == type(1):
  44.             return self.value+other
  45.         if type(other) == type(self):
  46.             return self.value + other.value

  47.     def __sub__(self,other):
  48.         return self.value - other.value
  49.     def __mul__(self,other):
  50.         return other.__sub__(self)
  51.     def __truediv__(self,other):
  52.         return self.value/other.value
  53.     def __radd__(self,other):
  54.         return self.__add__(other)
  55.     def __It__(self,other):
  56.         if self.value > other.value:
  57.             return False
  58.         if self.value < other.value:
  59.             return True

  60. class Eee:
  61.     def __init__(self):
  62.         self.x = 2
  63.         self.y = 4
  64.     def __call__(self,a,b):
  65.         return Ccc(a,b)
复制代码

我们运行一下,然后在shell里面输入下面的调用:
>>> mmm = Eee()
>>> ff = mmm(2,5)
>>> ff.name
[1, 2, 3, 2]
>>> ff.value
125
>>> ff.pompt
'雾草'
>>> ff.wocao
buzai
>>> ff.pompt
'被更新'
>>> 1 + ff
126
>>> ff + 1
126
>>> len(ff)
11
3
>>> nn = mmm(3,4)
>>> nn.name
[1, 2, 3, 3]
>>> nn.value
64
>>> ff + nn
189
>>> nn + ff
189
>>> ff/nn
1.953125
>>> nn/ff
0.512
>>> del ff
shanle
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-7 17:23:24 | 显示全部楼层
夕阳游龙 发表于 2015-10-7 16:42
return和print毫无关系的,你的例子中a() = 'I love fishC.com',也就是函数a()的值是'I love fishC.com' ...
  1. >>> mmm = Eee()
  2. >>> ff = mmm(2,5)
  3. >>> ff.name
  4. [1, 2, 3, 2]
  5. >>> ff.value
  6. 125
  7. >>> ff.pompt
  8. '雾草'
  9. >>> ff.wocao
  10. buzai
  11. >>> ff.pompt
  12. '被更新'
  13. >>> 1 + ff
  14. 126
  15. >>> ff + 1
  16. 126
  17. >>> len(ff)
  18. 11
  19. 3
  20. >>> nn = mmm(3,4)
  21. >>> nn.name
  22. [1, 2, 3, 3]
  23. >>> nn.value
  24. 64
  25. >>> ff + nn
  26. 189
  27. >>> nn + ff
  28. 189
  29. >>> ff/nn
  30. 1.953125
  31. >>> nn/ff
  32. 0.512
  33. >>> del ff
  34. shanle
复制代码


01 实例mmm,不会有显示,
02 ff = mmm(2,5) 直接是Eee()中的def __call__ (mmm,2,5)调用,然后返回了将参数传入类Ccc,也即Ccc(ff,2,5)这一实例,然后我们来看下实例ff都有哪些属性
03 ff中有name 的属性(是不是感觉跟调用字符串的方法相像),然后得到ff.name 的值
05ff中的value 属性
07 ff 中prompt属性
09 我们看看ff中有没有wocao这个属性,显然没有,由于我们访问不存在的属性,因而魔法方法(4楼代码33行)  __getattr__被触发,执行了34行的print('buzai'),然后self.pompt = ‘被更新',将ff的pompt属性给重新赋值了
11 我们再访问ff的属性pompt时,就变成'被更新' (执行了09就被重新赋值了)
然后我们看看我定义的将实例ff进行左加和右加可不可以实行,是可以的
17句为什么len(ff) 和我们平时理解的len([1,2,3,4])等这样的不一样了,因为我在Ccc中(4楼23行代码)改写了__len__(self),那么当调用len(ff)时自动触发__len__,执行了print('11')和返回len([1,2,3])的值

nn和ff一样两个不同实例(这就是面向对象编程的好处和优点,我们不必要单独为对一个事物写函数和代码,就像人类,美国人,中国人,他们之间有相同点都是人,都有共性,可以创建父类人类,然后美国人一个子类继承父类人类,就具有了人类的所有特性,然后可以再单独修改美国人的特性(黄头发,蓝眼睛等等),不扯了,
然后nn和ff可以正加和反加,以及正除反除操作,由于我没有定义幂运算,所以你可以试试
ff**2和2**ff以及ff**nn等,肯定都会报错,因为我没有定义这个运算,在shell里输入2**ff系统就会不知道怎么操作了!



评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +5 收起 理由
~风介~ + 5 + 5 + 5 感谢楼主无私奉献!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-7 19:34:00 | 显示全部楼层
本帖最后由 1245722417 于 2015-10-7 19:35 编辑
夕阳游龙 发表于 2015-10-7 11:47
问题1:递归不是需要调用return才会递归,return 是函数又返回值(返回值可以是数字,字符串,列表,字典, ...


根据你的解答我又研究了一下午。。。觉得说得很有道理
然后据此我又对自己总结了若干心得,不知对不对
        1. 有了for循环,for肯定希望序列的每个元素都遍历到
        2. 有了(10.search_file(each_file, target) # 递归调用),要等它递归完了才会执行(11.os.chdir(os.pardir) # 递归调用后切记返回上一层目录)
        3. 此例虽然是递归,但从整个递归函数看,for循环遍历是含在它里面的,而不是递归被循环包裹
                a. 也就是说每一次递归,都要for循环遍历一次,每一次遍历只是把这一次所在目录下所有元素遍历一次,每一次都重新按这一次遍历结果顺序来执行
                b. 当执行到目录的最底层,已无元素可遍历时,那一次的for循环结束,自然这个each_file的递归也结束,因为电脑中目录层级有限,所以此例中递归不会无限执行下去
                c. 根据我测试的结果当这个时候注释掉#os.chdir(os.pardir)的话,程序就被卡住了,所以执行返回上一级目录,另一次for循环就会启动,执行这一次for循环,对它遍历结果的下一个元素执行相应操作,在新的each_file下递归继续。
        4. 至于为什么每一次for循环后,只返回上层目录一级,而不是设计成直接跳到初始目录再递归下去呢?我还不是很明白,隐约感觉是因为os.chdir(os.pardir)这句话其实也是包含在递归函数的,所以当递归执行时,从目录中自下而上把每一层的目录都照顾到。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-7 19:56:10 | 显示全部楼层
夕阳游龙 发表于 2015-10-7 17:23
01 实例mmm,不会有显示,
02 ff = mmm(2,5) 直接是Eee()中的def __call__ (mmm,2,5)调用,然后返回 ...

我还看不大懂,于是就直接看你写的结论了,感觉类就是定义了若干属性,‘美国人’就是在这些属性里面付给相应的特定值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-7 20:00:57 | 显示全部楼层
学习~~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-7 21:12:56 | 显示全部楼层
1245722417 发表于 2015-10-7 19:34
根据你的解答我又研究了一下午。。。觉得说得很有道理
然后据此我又对自己总结了若干心得,不知对不对 ...

嗯嗯,1,2,3(a,b,c)条理解很到位,我花这么多时间给你写啊!!!,就怕你听不明白,我想你应该了解了,怎么来看计算机执行程序的顺序了!这题其实就是递归后,for循环然后,for循环再套for循环,然后再递归,再for循环套for循环,这个就是很耗时间(如果感兴趣,可以了解下算法,for循环是线性算法的,里面再套for循环就变成平方了,不了解也没关系,毫无影响!!!),目录有限因而会跳出递归。
举个例子来说:
我的电脑F盘,F:目录下三个文件(文件夹1,文件夹2,你好.txt)。文件夹1里面有(lian.py, 你好.txt,新建文件夹),新建文件夹里面(你好.txt),文件夹2里面(你好.txt).
那么F盘总共会有多少个有效的目录:
1.  F:
2   F:/文件夹1
3   F:/文件夹1/新建文件夹
4   F:/文件夹2
就这四个,然后我们设置的初始是F:,目标是找:你好.txt
最外层for大循环时os.listdir(os.curdir) = ['文件夹1',’文件夹2','你好.txt']  路径是F:
each_file = '文件夹1',显然不等于target,那么才会(if os.path.isdir(each_file)),当前路径F:
而F:/each_file目录刚好存在是True(由于each_file 这时是each_file='文件夹1',那么F:/each_file,也即
目录F:/文件夹1,是存在的,而当each_file=‘你好'.txt 时 ,路径F:/你好.txt,以及后面的
F:/文件夹1/lian.py,不是目录,而只是一个文件的路径,而os.path.isdir是判断路径是否是一个目录,小甲鱼的原话!!也即必须是一个目录才会为True。)所以当each_file = '文件夹1'时递归,实参变成each_file,
也就是文件夹1,然后os.chdir(each_file) 就把当前目录改到F:/文件夹1,此时for又有['新建文件夹','ian.py', '你好.txt'],然后一个个来执行,each_file = 新建文件夹,再次递归,这时递归的each_file = '新建文件',然后当前目录被os.chdir('新建文件夹')改为F:/文件1/新建文件夹,新建文件夹里面就一个'你好'.txt,因而一次for就完事了,直接进入if each_file == target :然后打印了路径,记住此时当前目录:F:/F:/文件1/新建文件夹,如果不执行11的os.chdir(os.pardir),返回上一目录,那么for循环会在F:/文件1/新建文件夹里,因为for在函数代码04行的os.chdir(start_dir)下面,是不会初始化的,因而
06的for each_file in os.listdir(os.curdir) : 中的os.curdir是指当前目录,也就是此时的F:/文件1/新建文件夹,不会改变,然而上一层目录(F:/文件1)中还有两个文件['lian.py', '你好.txt']没有被函数判断和执行到,同理上一层F:中也有['文件2','你好.txr']没判断执行,所以我们必须从最底层目录一层一层的回来,也就是要返回上一目录F:/文件1,循环另两个文件,然后再返回F:中执行另两个文件!!!!


问题4;答案是函数中04行代码os.chdir(start_dir),在06行的代码前,递归一次会循环很多次,除非碰到文件夹再次递归,才会改变路径,而改变路径只会改成os.chidir('文件1'),变成F:/文件1,然后再次递归的话os.chidir('新建文件夹'),即变成F:/文件1/新建文件夹,
注意:start_dir只是函数的形参,search_file(each_file,target)时形参都会换成each_file,变成os.chdir(each_file),确实是包含在递归中,但是参数变了,也即递归每次的实参会变!!!

相信你也懂了,今天为了给你讲耽误我至少四个小时来组织文字给你讲清楚!!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-7 21:57:57 | 显示全部楼层
1245722417 发表于 2015-10-7 19:56
我还看不大懂,于是就直接看你写的结论了,感觉类就是定义了若干属性,‘美国人’就是在这些属性里面付给 ...

嗯,学到面向对像编程时,不要着急,确实很难懂,因为对象类,实例等等确实很难理解,而且各种魔法方法,多练代码!有静态属性,也有动态的,可变不可变的,有属性当然也会定义各种动作等等!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-8 00:55:06 | 显示全部楼层
夕阳游龙 发表于 2015-10-7 21:12
嗯嗯,1,2,3(a,b,c)条理解很到位,我花这么多时间给你写啊!!!,就怕你听不明白,我想你应该了解了,怎 ...

十分感谢!!!

不好意思。。。还有另一个疑问,就是你说的这个汉诺塔的案例
其实汉诺塔实现的思路我觉得自己应该是明白的,但是小甲鱼的代码我一直没看懂。。。不知道这些代码是怎么实现右边注释里的步骤思路的。。。
如果你有时间。。。求解答,谢谢!!!
  1. def hanota(n,x='x',y='y',z='z'):
  2.     if n == 1:
  3.         print(x,'-->',z)
  4.     else:
  5.         hanota(n-1,x,z,y)#将前n-1个盘子从x移到y上
  6.         print(x,'-->',z)#将底下的最后一个盘子从x移到z
  7.         hanota(n-1,y,x,z)#将y的n-1个盘子移到z上
  8. print(hanota(2))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-8 19:21:14 | 显示全部楼层
顶顶顶
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-8 21:41:55 | 显示全部楼层
感谢楼主谢谢你 学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-9 14:24:34 | 显示全部楼层
1245722417 发表于 2015-10-8 00:55
十分感谢!!!

不好意思。。。还有另一个疑问,就是你说的这个汉诺塔的案例

我发了一篇帖子详细来讲汉诺塔![url=小甲鱼中关于汉诺塔的详细步骤讲解 http://bbs.fishc.com/thread-65362-1-1.html (出处: 鱼C论坛)]汉诺塔详细讲解[/url]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-10 01:03:13 | 显示全部楼层
夕阳游龙 发表于 2015-10-9 14:24
我发了一篇帖子详细来讲汉诺塔!http://bbs.fishc.com/thread-65362-1-1.html (出处: 鱼C论坛)]汉诺塔详 ...

感谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-11-30 13:53:09 | 显示全部楼层
学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-12-8 17:35:15 | 显示全部楼层
十分不错,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-11-29 22:00:46 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-1-25 20:35:31 | 显示全部楼层
这帖子很好,目前水平有限,魔法方法以后学到再来看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-12-19 20:02:27 | 显示全部楼层
学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-28 19:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表