侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

python的基本知识点

2023-11-26 星期日 / 0 评论 / 0 点赞 / 59 阅读 / 49441 字

python的历史 `````````````````````````````````````````````````````````````````````` + python发音 * Pyth

python的历史
``````````````````````````````````````````````````````````````````````

    + python发音

        * Python ([KK] 英语发音:  /'paɪθɑn/, [DJ] 英语发音:  /ˈpaiθən/)

    + 什么是python?

        * 一种强类型动态脚本编程语言

            - 强类型: a=0, b='0', a为整型, b为字符型. 不能把a当作字符, 也不能把b当作整数(除非被重新赋值)
            - 动态类型: 不需要申明, 变量的类型可以随着被重新赋值而改变.

        * 同时也是python语句的解释器

            - 解释性语言, 不需要编译

    + python之父

        * Guido Van Rossum, 1960-?, 荷兰阿姆斯特丹, 1995年移居美国, 2005年加入Google
        * 1990年Guido为了打发圣诞节的无趣, 在ABC(他参与设计的另一种编程语言)基础上, 创造了"Python"

    + "Python"命名的由来

        * Guido是一个 Monty Python's Flying Circus 飞行马戏团的爱好者

    + python的实现(Implementations)

        * Cpython(一般使用的就是这个版本)
        * Jpython(Java虚拟机上的实现)
        * Ironpython(.NET平台上的实现)

    + 为什么选择Python?

        语言就是工具, 选择语言就是选择工具

        1. 简单易学
        2. 解释性
        3. 面向对象
        4. 高级语言
        5. 可扩展性及可嵌入性
        6. 免费、开源
        7. 可移植性
        8. 丰富的库
        9. 足够流行

Python基本知识
``````````````````````````````````````````````````````````````````````

    + 运行Python的方法

        * shell中执行python即进入python解释器, 解释里可以执行python的语句(大多数Linux发行版默认安装)
        * 解释器里执行: execfile("filename.py")
        * 写在文本文件中, 第一行为"魔法字符", 一般为"#!/usr/bin/env python", 使用'python filename.py', 或者加上执行权限作作为程序执行.

    + 退出解释器

        * 文档结束标志(EOF)
        * 内建函数: exit()
        * sys模块: import sys;sys.exit()
        * 引发异常: raise SystemExit

    + Python中没有像C语言中的"{}", ";", 取而代之是就是"缩进", 使用换行和行首相同数量的空白来区分语句与代码块.
    + 以井号"#"为注释符, 另外,python中的doc strings也算是一种注释, 但它会被程序读取并可以在程序中使用(后面定义函数与类的时候再讲)
    + 分号";"允许在同一行上写多个语句(类似于shell, 但不推荐, 会降低代码的可读性)
    + print语句: 相当于shell中的"echo -e"
    + 大小写敏感
    + 不要在脚本里混用制表符和空格来缩进, 建议使用4个空格代替制表符
    + 中文支持: 在脚本第二行添加"#coding:utf8"或"#coding:gbk"字样
    + 命令行下查找文档: pydoc
    + 解释器里查看帮助: help()
    + python中的常用内建函数: dir(__builtins__), help, dir, id ...

Python基础语法
``````````````````````````````````````````````````````````````````````

* 变量和表达式

        * 不需要申明变量及类型
        * 变量名字符与shell类似, 但是还有特殊变量
        * 表达式
        * "="号赋值, "=="判断. (与C不一样, Python不支持行内赋值)
        * 变量可以被重新赋值, 获得新的类型(动态)
        * 引用变量: 直接使用变量名, 不用加$.
        * 交换变量值::

            a, b = b, a

* 条件语句

        * if和else语句, 语句块用缩近来表示, else子句在某些情况下可以省略.  如果if或else语句块只有一个语句, 也可以不使用缩近说::

            if <条件表达式>:
                 <语句>
            else:
                 <语句>

            if a<b: z=a
            else: z=b

            这样的写法也是合法的, 但这不是推荐的作法. 一直使用缩近可以让你方便的在语句体中添加一个语句, 而且读起来更清晰.

        * 若某个子句不需任何操作,就使用pass语句, 相当于shell中的":"号
        * 通过使用 or,and 和 not 关键字可以建立任意的条件表达式
        * 用 elif 语句可以检验多重条件(用于代替其它语言中的switch语句)
        * 下面对象的布尔值为False

            - None
            - False (布尔类型)
            - 所有的值为零的数

                + 0     (整型)
                + 0.0   (浮点型)
                + 0L    (长整型)
                + 0.0+0.0j  (复数)

            - "" (空字符串)
            - [] (空列表)
            - () (空元组)
            - {} (空字典)

* 文件输入/输出

        * 打开一个文件, 使用file()或open()创建文件对象, 推荐open()
        * 通过调用文件对象的不同方法可以对文件进行不同的操作::

            f = open('file.txt','w')    # 写
            f = open('file.txt','a')    # 追加
            f = open('file.txt','rb')   # 读二进制文件
            加入b, 表示以二进制方式读写

        * 读取文件内容的几个常用"对象的方法"::

            data = f.read()         # 一次性读取所有内容
            line = f.readline()     # 一次读一行, 一般与循环一起使用, 返回str
            lines = f.readlines()   # 读取所有行, 返回list, 一行一个元素

        * 如果文件不存在, 以"读"方式创建文件对象时会报错.
        * 要将程序的输出内容由屏幕重定向到文件中, 可以使用'>>'运算符, 如下例::

            f = open("out","w")     # Open file for writing
            print >>f,"%3d %0.2f" % (year,principal)  #将格式文本输出到文件对象f
            f.close()

        * 文件对象也拥有write()方法, 通过它可以向文件对象写入新的数据::

            f.write("%3d %0.2f/n" % (year,principal))

        * 文件处理完之后, 记得关闭文件对象::

            f.close()

* 字符串

        * 要创建一个字符串, 你使用单引号,双引号或三引号将其引起来

            * 一个字符串用什么引号开头, 就必须用什么引号结尾.
            * 单引号与双引号只能创建单行字符串, 两个三引号之间的一切字符(包括换行)都是字符串的内容

        * 三引号能够创建多行字符串

        * 字符串是一个以0开始, 整数索引的字符序列, 要获得字符串s中的第i+1个字符, 使用索引运算符s[i]

        * 切片运算符s[i:j], 获得子串. 它返回字符串s中从索引i(包括i)到j(不包括j)之间的子串. 若i被省略, python就认为i=0, 若j被省略, python就认为j=len(s)-1

        * 可以用加(+)运算符来连结字符串

        * 格式化字符串::

            包含普通文本及格式化字符序列(例如"%d", "%s", 和 "%f"),这些序列决定特定类型的数据(如整型,字符串,浮点数)的输出格式.'%3d'将一个整数在宽度为3个字符的栏中右对齐,'%0.2f'将一个浮点数的小数点后部分转换为2位. 格式字符串的作用和C语言中的sprintf()函数基本相同.

            print "%3d %0.2f" % (year, principal)

        * 通过使用str()函数,repr()函数或反引号(`)可以将其他类型的数据转换为字符串::

            s = "The value of x is " + str(x)
            s = "The value of y is " + repr(y)
            s = "The value of y is " + `y`

        * str()与repr()的区别, repr()函数用来取得对象的规范字符串表示, 反引号(`)是repr()函数的快捷版::

            >>> print str("/n")
            >>> print repr("/n")

* 列表和元组(Lists & Tuples)

        * 如同字符串是字符的序列,列表和元组则是任意对象组成的序列

        * 列表和元组都是以整数0来开始索引的序列, 可以用索引操作符来读取或者修改列表中特定元素的值::

            a = names[2]             # Returns the third item of the list, "Ann"
            names[0] = "Jeff"        # Changes the first item to "Jeff"

        * 用len()内建函数得到列表的长度::

            print len(names)        # prints 4

        * append()方法可以把一个新元素插入列表的末尾 ::

            names.append("Kate")

        * insert()方法可以把新元素插入到列表::

            names.insert(2, "Sydney")   # 插入到原来索引2之前

        * 删除元素::

            del name[2]

        * 用切片操作符可以取出一个子列表或者对子列表重新赋值::

            b = names[0:2]                      # Returns [ "Jeff", "Mark" ]
            c = names[2:]                       # Returns [ "Sydney", "Ann", "Phil", "Kate" ]
            names[1] = 'Jeff'                   # Replace the 2nd item in names with "Jeff"
            names[0:2] = ['Dave','Mark','Jeff'] # 用右边的 list 替换 names 列表中的前两个元素

            常用[:]来取一个列表的拷贝并进行操作

        * 加(+)运算符可以连结列表::

            a = [1,2,3] + [4,5]     # Result is [1,2,3,4,5]

        * 列表元素可以是任意的 Python 对象,当然也包括列表::

            a = [1,"Dave",3.14, ["Mark", 7, 9, [100,101]], 10]

        * 子列表的元素用下面的方式调用 ::

            a[1]            # Returns "Dave"
            a[3][2]         # Returns 9
            a[3][3][1]      # Returns 101


        * 列表的高级特性(列表解析)::

            print [x*2 for x in range(10)]
            print [x*2 for x in range(10) if x >3]

        * 元组(tuple)类型和列表关系很密切,通过用圆括号中将一系列逗号分割的值括起来可以得到一个元组::

            a = (1,4,5,-9,10)
            b = (7,)                                 # 一个元素的元组一定要加一个额外的逗号
            person = (first_name, last_name, phone)

        * 在某些时候, 即使没有圆括号, Python仍然可以根据上下文认出这是一个元组

        * 元组支持大多数列表的操作, 比如索引,切片和连结
        * 元组与列表之间一个关键的不同是不能在一个tuple创建之后修改它的内容. 也就是说,你不能修改其中的元素,也不能给tuple添加新的元素.
        * list, tuple 其他的一些方法: dir(list), dir(tuple) (根据时间选几个常用的来讲)
        * list, tuple 相互转换: list(), tuple()

* 循环

        * while: 结束循环体的缩进表示块的结束::

            while <条件表达式>:
                <语句>


        * for循环, 迭代任何类型的一个序列(例如字符串,列表,或者tuple等)中的每个元素::

                for i in range(1,10):
                    print "2 to the %d power is %d" % (i, 2**i)

           - range(i,j)函数建立一个整数序列,这个序列从第 i 数开始(包括 i )到第 j 数为止(不包括 j). 若第一个数被省略, 它将被认为是0. 该函数还可以有第三个参数, 步进值, 见下面的例子

           - range()函数根据起始值, 终止值及步进值三个参数在内存中建立一个列表, 当需要一个很大的列表时,这个既占内存又费时间. 为了克服它的缺点,Python提供了xrange()函数::

                for i in xrange(1,10):
                        print "2 to the %d power is %d" % (i, 2**i)

                a = xrange(100000000)       # a = [0,1,2, ..., 99999999]
                b = xrange(0,100000000,5)   # b = [0,5,10, ...,99999995]

           - xrange()函数只有在需要值时才临时通过计算提供值, 节省内存.
        
        * 死循环

* 集合(set)(简单介绍)

        * 无序不重复元素集
        * 简单应用:

            + list(set([1,4,6,2,3,2,1,6]))      # 去除一个列表中的重复元素得到新的列表
            + 可以使用"&"和"|"求两个set的交集,并集::
                
                >>> a = [1,3,5,7]
                >>> b = [1,2,3,4]
                >>> s1,s2 = set(a),set(b)
                >>> print s1 & s2
                set([1, 3])
                >>> print s1 | s2
                set([1, 2, 3, 4, 5, 7])

* 字典

        * 字典就是一个关联数组(或称为哈希表)
        * 它是一个通过关键字索引的对象的集合(键值对, key:value)
        * 使用大括号{}来创建一个字典::

            a = {
                   "username" : "beazley",
                   "home" : "/home/beazley",
                   "uid" : 500
                }

        * 用关键字索引操作符可以访问字典的某个特定值

        * 插入或者修改对象::

            a["username"] = "pxl"
            a["home"] = "/home/pxl"
            a["shell"] = "/usr/bin/tcsh"

        * 可以使用 has_key() 方法来检验一个键/值对是否存在(或者in操作符)::

            if a.has_key("username"):
                 username = a["username"]
            else:
                 username = "unknown user"

        * 上边的操作还可以用更简单的方法完成::

            username = a.get("username", "unknown user")

        * 字典的keys() 方法返回由所有关键字组成的列表::

            k = a.keys()         # k = ["username","home","uid","shell"]

        * del语句可以删除字典中的特定元素::

            del a["username"]

* 函数

        * 使用def语句来创建函数, 可以定义参数::

            def remainder(a,b):
                    q = a/b
                    r = a - q*b
                    return r

        * 要调用一个函数, 只要使用函数名加上用括号括起来的参数就可以了::

            def divide(a,b):
                    q = a/b        # If a and b are integers, q is an integer
                    r = a - q*b
                    return (q,r)

        * 如果打算让函数返回多个值, 常用的方法就是让它返回一个元组. (返回一个列表也可以). 当返回一个tuple时, 这样调用函数很有用::

            quotient, remainder = divide(1456,33)

        * 可以给函数的参数指定默认值::

            def connect(hostname,port,timeout=300):
                  # Function body

        * 若在函数定义的时候提供了默认参数, 那么在调用函数时就允许省略这个参数::

            connect('www.python.org', 80)

        * 也可以使用关键字参数来调用函数,这样参数就可以使用任意顺序::

            connect(port=80,hostname="www.python.org")

        * 函数内部定义的变量为局部变量, 要想在一个函数内部改变一个全局变量的值, 在函数中使用global语句::

            a = 4.5
            ...
            def foo():
                    global a
                    a = 8.8             # 改变全局变量 a

* 类

        * Python支持面向对象编程, 在面向对象编程中, class语句用于定义新类型的对象::

            class myclass:
                '''my class's doc strings '''
                def __init__(self):
                    print self.__doc__
            
                def myfunc(self,a,b):
                    '''my function's doc strings'''
                    return a*b

        * doc strings: 必须是定义类名的下一行, 并缩进.
        * 在类定义中, 用def语句定义类的方法.
        * 类中每个方法的第一个参数总是引用类实例对象本身, 习惯上使用self来代表这个参数(仅仅是习惯)
        * 类的方法中若需要调用实例对象的属性则必须显式使用self变量(如上所示)
        * 方法名中若前后均有两个下划线, 则表示这是一个特殊方法, 比如init方法被用来初始化一个对象(实例)
        * 使用一个类::

            s = myclass()       # 创建一个类的对象
            s.myfunc(2,6)       # 调用对象的方法
            del s               # 删除对象

* 异常

        * 如果在程序中发生了一个错误, 就会引发异常(exception)::

            Traceback (most recent call last):
                File "<interactive input>", line 42, in foo.py
            NameError: a

        * 错误信息指出了发生的错误类型及出错位置, 通常情况下, 错误会导致程序终止
        * 可以使用 try 和 except 语句来捕获并处理异常::

            try:
                f = open("file.txt","r")
            except IOError, e:
                print e

            表示: 如果有 IOError 发生, 造成错误的详细原因将会被放置在对象e中, 然后运行 except 代码块.

        * 若发生异常, 系统就会将控制权转到处理该异常的except代码块, 如果没有找到该代码块, 程序将运行终止, 若没有异常发生, except代码块就被忽略掉

        * raise语句用来有意引发异常, 可以使用内建异常来引发异常::

            raise RuntimeError, "Unrecoverable error"

        * 也可以建立自己的异常
        * 可以在一个except内捕获多个异常::

            except (AttributeError, TypeError, SyntaxError):

        * 捕获所有异常, 只要在except后面不加任何异常类型, 这个except块就可以捕获所有的异常::

            except:

* 模块

        * Python允许你把函数定义或公共部分放入一个文件, 然后在其他程序或者脚本中将该文件作为一个模块导入. 要创建一个模块, 把相应的语句和定义放入一个文件, 这个文件名就是模块名.
        * 模块文件, 约定的是以.py为扩展名(Unix/Linux也一样). 并不是所有的模块都保存为.py文件,还有内置模块(C语言编写)
        * 当py脚本被当作模块导入之后, 会根据需要自动生成一个以.pyc结尾的二进制文件.
        * 这个二进制文件不会提高程序的执行效率, 但可以提高模块导入的速度(当然, 这对程序的运行也是有益的).
        * 这个二进制文件也是可以当作脚本来执行的(但要有x权限), 如果脚本里有"不为人知"的"秘密", 也可以简单的使用这种方法
        * doc strings: 必须在模块的第一个非注释行之前.
        * 要在其它的程序中使用模块, 使用import语句::

            # define
            # file : div.py
            '''This is a module's 'doc strings''''
            def divide(a,b):
                '''This is a function's 'doc strings''''
                q = a/b        # If a and b are integers, q is an integer
                r = a - q*b
                return (q,r)

            # use
            import div
            a, b = div.divide(2305, 29)

        * import语句创建一个新的名字空间, 该空间包含模块中所有定义对象的名称. 要访问这个名字空间, 把模块名作为一个前缀来使用这个模块内的对象::

            div.divide()

        * 如果想使用一个不同的模块名字访问这个模块, import语句加上一个"as <模块名>"就可以了::

            import div as foo
            a,b = foo.divide(2305,29)

        * 如果只想导入指定的对象到当前的名称空间,使用 from 语句::

            from div import divide
            a,b = divide(2305,29)       # No longer need the div prefix (不再需要div前缀)

        * 导入一个模块中的所有内容到当前的名称空间::

            from div import *

        * 内建函数dir()可以列出一个模块(以及所有对象, python中"一切皆对象")中的所有可访问内容. 在python交互环境中测试一个模块的功能时, 这会是一个很有用的工具, 因为它可以提供一个包含可用函数及变量的列表::

            >>> import string
            >>> dir(string)
            ['_ _builtins_ _', '_ _doc_ _', '_ _file_ _', '_ _name_ _', '_idmap',
             '_idmapL', '_lower', '_swapcase', '_upper', 'atof', 'atof_error',
             'atoi', 'atoi_error', 'atol', 'atol_error', 'capitalize',
             'capwords', 'center', 'count', 'digits', 'expandtabs', 'find',
            ...
            >>>

        * 导入模块时的搜索路径::

            import sys
            sys.path        # path不是方法, 而是sys内建模块的一个属性(变量). 这相当于shell中的$PATH(但不是查找命令, 而是查找模块)
            sys.path[0]     # 即为当前路径

        * 修改sys.path: 使用列表(list)的方法, type(sys.path)为list::

            sys.path.append('/opt/py')
            sys.path.insert(1, '/opt/pyMod')
            del sys.path[1]

.. Python的哲学

    * 没有"实际用途"的模块: "this" ::

        >>> import this
        The Zen of Python, by Tim Peters
        Beautiful is better than ugly.
        Explicit is better than implicit.
        Simple is better than complex.
        Complex is better than complicated.
        Flat is better than nested.
        Sparse is better than dense.
        Readability counts.
        Special cases aren't special enough to break the rules.
        Although practicality beats purity.
        Errors should never pass silently.
        Unless explicitly silenced.
        In the face of ambiguity, refuse the temptation to guess.
        There should be one-- and preferably only one --obvious way to do it.
        Although that way may not be obvious at first unless you're Dutch.
        Now is better than never.
        Although never is often better than *right* now.
        If the implementation is hard to explain, it's a bad idea.
        If the implementation is easy to explain, it may be a good idea.
        Namespaces are one honking great idea -- let's do more of those!
        >>>
        这就是"Python之禅", "Python的哲学"!

Python脚本讲解
``````````````````````````````````````````````````````````````````````

* 99乘法表

    + for
    + 格式化字符串
    + 讲解::
    
        print "".join([('%s*%s=%s%s' % (y,x,x*y,'/n' if x==y else '/t')) for x in range(1,10) for y in range(1,10) if x >= y])

               |
               |--> python中"一切皆对象", 这里是调用字符串""(空字符串)对象的join方法(用""来连接join的参数(的元素))

        for x in range(1,10):
            for y in range(1,10):
                if x>=y:
                    print '%s*%s=%s%s' % (y,x,x*y,'/n' if x==y else '/t'),
        这里的'/n' if x==y else '/t'相当于C语言中的三元运算符 x=y?'/n':'/t'

* 猜数字游戏

    + raw_input()
    + int()
    + random模块
    + if

* this模块

    + for
    + 列表解析
    + 字典

* /usr/bin/yum脚本
* 邮件发送脚本(脚本在example/sdmail/下)

    + smtplib模块

        - smtplib.SMTP()
        - self.login()
        - self.sendmail()
        - 登录异常处理 try:except

    + getpass模块(模块最后20行介绍, 跨平台支持)
    + sys模块

        - sys.argv
        - sys.stderr
        - sys.stdin --> pipe

    + os模块

        - os.path.isfile()

    + time模块

        - 查看当前时间

    + email模块(可选)

        - 支持发送附件

* oracle数据库热备脚本(还没有讲到数据库,可选, 脚本在example/下)

    + 数据库应用编程接口(DB-API)与数据库对象映射框架(ORM)简单介绍
    + 安装python非标准模块(库)的方法

        - python-setuptools: easy_intall cx_Oracle
        - 源代码: python setup.py install

    + 使用DB-API的一般步骤:

        1. 创建数据库连接对象
        2. 创建游标对象
        3. 在游标对象上执行SQL语句
        4. 关闭数据库连接对象

    + shutil模块

        - shutil.copy()

* 备份脚本, 学员动手写, 不做要求

    + os模块: os.system()
    + popen2模块: popen2.popen2()
    + optparse模块
    + 可使用参数决定是否交互
    + 压缩备份文件
    + 备份文件按日期存放

.. this.py

    d = {}
    for c in (65, 97):
        for i in range(26):
            d[chr(i+c)] = chr((i+13) % 26 + c)
    #   print "%s ---> %s" % (chr(i+c),chr((i+13) % 26 + c))
    #
    #print s
    #print
    print "".join([d.get(c, c) for c in s])
    print d

    # chr(i)   --> 0 <= i < 256
    # i 对应"man ascii"中的Dec值(10进制)

    # c = 65  --> 10进制,大写字母A  # c = 97  --> 10进制,小写字母a
    # i = 0
    # d[chr(65)] = chr(13%26+65) = chr(13+65) = chr(78)
    # d['A'] = 'N'
    # d = {'A':'N'}

    # c = 65
    # i = 1
    # d[chr(66)] = chr(14%26+65) = chr(14+65)
    # d['B'] = 'O'
    # d = {'A':'N', 'B':'O', ...}

    # print "".join([d.get(c, c) for c in s])
    # 列表解析.
    #
    # 从s里取出字符c, 如果c是字典d里的key, 则取出对应的value, 如果不是, 则返回原字符c, 最后得到一个list(列表)
    # 再用""(空)join(连接)这个列表里的元素(成员).

..    * T恤: 人生苦短, 我用 Python_!

.. 中文翻译

        Python之禅 by Tim Peters

        优美胜于丑陋 (Python 以编写优美的代码为目标)
        明了胜于晦涩 (优美的代码应当是明了的, 命名规范, 风格相似)
        简洁胜于复杂 (优美的代码应当是简洁的, 不要有复杂的内部实现)
        复杂胜于凌乱 (如果复杂不可避免, 那代码间也不能有难懂的关系, 要保持接口简洁)
        扁平胜于嵌套 (优美的代码应当是扁平的, 不能有太多的嵌套)
        间隔胜于紧凑 (优美的代码有适当的间隔, 不要奢望一行代码解决问题)
        可读性很重要 (优美的代码是可读的)
        即便假借特例的实用性之名, 也不可违背这些规则 (这些规则至高无上)

        不要包容所有错误, 除非你确定需要这样做 (精准地捕获异常, 不写 except:pass 风格的代码)

        当存在多种可能, 不要尝试去猜测
        而是尽量找一种, 最好是唯一一种明显的解决方案 (如果不确定, 就用穷举法)
        虽然这并不容易, 因为你不是 Python 之父 (这里的 Dutch 是指 Guido )

        做也许好过不做, 但不假思索就动手还不如不做 (动手之前要细思量)

        如果你无法向人描述你的方案, 那肯定不是一个好方案;反之亦然 (方案测评标准)

        命名空间是一种绝妙的理念, 我们应当多加利用(倡导与号召)
        接下来, 我们看一下 this 这个模块. 故作高深? 反例?

.. man ascii
    代码解释: Dec: 10进制 Hx: 16进制 Oct: 8进制 Char: 字符

.. python的相关介绍:
    python 之父 1960年, Guido Van Rossum出生在荷兰阿姆斯特丹
    Python ([KK] 英语发音:  /'paɪθɑn/, [DJ] 英语发音:  /ˈpaiθən/)
    命名: Monty Python's Flying Circus (蒙提•派森飞行马戏团) , 他是这个肥皂剧的狂热粉丝

 

广告 广告

评论区