精华内容
下载资源
问答
  •   作为一名前端工程师,必须搞...这里说明一点,__proto__属性的两边是各由两个下划线构成(这里为了方便大家看清,在两下划线之间加入了一个空格:_ _proto_ _)。   现在正式开始!让我们从如下一个简单的例...

    提示:不要排斥,静下心来,认真读完,你就搞懂了!(可以先看一下最后的总结部分再回过头来完整看完)

    1. 前言

      作为一名前端工程师,必须搞懂JS中的prototype__proto__constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞懂它们。这里说明一点,__proto__属性的两边是各由两个下划线构成(这里为了方便大家看清,在两下划线之间加入了一个空格:_ _proto_ _,读作“dunder proto”,“double underscore proto”的缩写),实际上,该属性在ES标准定义中的名字应该是[[Prototype]],具体实现是由浏览器代理自己实现,谷歌浏览器的实现就是将[[Prototype]]命名为__proto__,大家清楚这个标准定义与具体实现的区别即可(名字有所差异,功能是一样的),可以通过该方式检测引擎是否支持这个属性:Object.getPrototypeOf({__proto__: null}) === null。本文基于谷歌浏览器(版本 72.0.3626.121)的实验结果所得。
       现在正式开始! 让我们从如下一个简单的例子展开讨论,并配以相关的图帮助理解:

    function Foo() {...};
    let f1 = new Foo();
    

    以上代码表示创建一个构造函数Foo(),并用new关键字实例化该构造函数得到一个实例化对象f1。这里稍微补充一下new操作符将函数作为构造器进行调用时的过程:函数被调用,然后新创建一个对象,并且成了函数的上下文(也就是此时函数内部的this是指向该新创建的对象,这意味着我们可以在构造器函数内部通过this参数初始化值),最后返回该新对象的引用,详细请看:详解JavaScript中的new操作符。虽然是简简单单的两行代码,然而它们背后的关系却是错综复杂的,如下图所示:
    整体的联系看到这图别怕,让我们一步步剖析,彻底搞懂它们!
      图的说明:右下角为图例,红色箭头表示__proto__属性指向、绿色箭头表示prototype属性的指向、棕色实线箭头表示本身具有的constructor属性的指向,棕色虚线箭头表示继承而来的constructor属性的指向;蓝色方块表示对象,浅绿色方块表示函数(这里为了更好看清,Foo()仅代表是函数,并不是指执行函数Foo后得到的结果,图中的其他函数同理)。图的中间部分即为它们之间的联系,图的最左边即为例子代码。

    2. _ _ proto _ _ 属性

      首先,我们需要牢记两点:①__proto__constructor属性是对象所独有的;② prototype属性是函数所独有的。但是由于JS中函数也是一种对象,所以函数也拥有__proto__constructor属性,这点是致使我们产生困惑的很大原因之一。上图有点复杂,我们把它按照属性分别拆开,然后进行分析:
    __proto__
      第一,这里我们仅留下 __proto__ 属性,它是对象所独有的,可以看到__proto__属性都是由一个对象指向一个对象,即指向它们的原型对象(也可以理解为父对象),那么这个属性的作用是什么呢?它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找…直到原型链顶端null(可以理解为原始人。。。),再往上找就相当于在null上取值,会报错(可以理解为,再往上就已经不是“人”的范畴了,找不到了,到此结束,null为原型链的终点),由以上这种通过__proto__属性来连接对象直到null的一条链即为我们所谓的原型链
      其实我们平时调用的字符串方法、数组方法、对象方法、函数方法等都是靠__proto__继承而来的。

    3. prototype属性

      第二,接下来我们看 prototype 属性:
    prototype属性  prototype属性,别忘了一点,就是我们前面提到要牢记的两点中的第二点,它是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象,由此可知:f1.__proto__ === Foo.prototype,它们两个完全一样。那prototype属性的作用又是什么呢?它的作用就是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,其实会默认同时创建该函数的prototype对象。

    4. constructor属性

      最后,我们来看一下 constructor 属性:
    constructor属性  constructor属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来,继承而来的要结合__proto__属性查看会更清楚点,如下图所示),从上图中可以看出Function这个对象比较特殊,它的构造函数就是它自己(因为Function可以看成是一个函数,也可以是一个对象),所有函数和对象最终都是由Function构造函数得来,所以constructor属性的终点就是Function这个函数。
    constructor继承
      感谢网友的指出,这里解释一下上段中“每个对象都有构造函数”这句话。这里的意思是每个对象都可以找到其对应的constructor,因为创建对象的前提是需要有constructor,而这个constructor可能是对象自己本身显式定义的或者通过__proto__在原型链中找到的。而单从constructor这个属性来讲,只有prototype对象才有。每个函数在创建的时候,JS会同时创建一个该函数对应的prototype对象,而函数创建的对象.__proto__ === 该函数.prototype,该函数.prototype.constructor===该函数本身,故通过函数创建的对象即使自己没有constructor属性,它也能通过__proto__找到对应的constructor,所以任何对象最终都可以找到其构造函数(null如果当成对象的话,将null除外)。如下:
    constructor说明

    5. 总结

       总结一下:

    1. 我们需要牢记两点:①__proto__constructor属性是对象所独有的;② prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__constructor属性。
    2. __proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链
    3. prototype属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype
    4. constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function

      本文就此结束了,希望对那些对JS中的prototype__proto__constructor属性有困惑的同学有所帮助。

    最后,感谢这两篇博文,本文中的部分内容参考自这两篇博文:

    小彩蛋:实现继承(相对完美、优雅)

    function inherit(Child, Parent) {
         // 继承原型上的属性 
        Child.prototype = Object.create(Parent.prototype)
         // 修复 constructor
        Child.prototype.constructor = Child
        // 存储超类
        Child.super = Parent
        // 静态属性继承
        if (Object.setPrototypeOf) {
            // setPrototypeOf es6
            Object.setPrototypeOf(Child, Parent)
        } else if (Child.__proto__) {
            // __proto__ es6 引入,但是部分浏览器早已支持
            Child.__proto__ = Parent
        } else {
            // 兼容 IE10 等陈旧浏览器
            // 将 Parent 上的静态属性和方法拷贝一份到 Child 上,不会覆盖 Child 上的方法
            for (var k in Parent) {
                if (Parent.hasOwnProperty(k) && !(k in Child)) {
                    Child[k] = Parent[k]
                }
            }
        }
    }
    

    若对你有帮助,可以支持一下作者创作更多好文章哦,一分钱也是爱~
    赞赏码

    展开全文
  • Python中if __name__ == '__main__':的作用和原理

    万次阅读 多人点赞 2019-05-06 11:37:52
    if __name__ == '__main__':的作用 一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此if __name__ == 'main':的作用就是控制这两种...

    if __name__ == '__main__':的作用

    一个python文件通常有两种使用方法,第一是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此 if __name__ == 'main': 的作用就是控制这两种情况执行代码的过程,在 if __name__ == 'main': 下的代码只有在第一种情况下(即文件作为脚本直接执行)才会被执行,而 import 到其他脚本中是不会被执行的。举例说明如下:

    • 直接执行

    直接执行 test.py,结果如下图,可以成功 print 两行字符串。即,if __name__=="__main__": 语句之前和之后的代码都被执行。

    • import 执行

    然后在同一文件夹新建名称为 import_test.py 的脚本,输入如下代码:

    执行 import_test.py 脚本,输出结果如下:

    只输出了第一行字符串。即,if __name__=="__main__": 之前的语句被执行,之后的没有被执行。

    if __name__ == '__main__':的运行原理

    每个python模块(python文件,也就是此处的 test.py 和 import_test.py)都包含内置的变量 __name__,当该模块被直接执行的时候,__name__ 等于文件名(包含后缀 .py );如果该模块 import 到其他模块中,则该模块的 __name__ 等于模块名称(不包含后缀.py)。

     “__main__” 始终指当前执行模块的名称(包含后缀.py)。进而当模块被直接执行,__name__ == 'main' 结果为真。

    为了进一步说明,我们在 test.py 脚本的 if __name__=="__main__": 之前加入 print(__name__),即将 __name__ 打印出来。文件内容和结果如下:

    可以看出,此时变量__name__的值为"__main__"。

    再执行 import_test.py,执行结果如下:

     

    此时,test.py中的__name__变量值为 test,不满足 __name__=="__main__" 的条件,因此,无法执行其后的代码。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     


     

     

     

    展开全文
  • 如何简单地理解Python中的if __name__ == '__main__'

    万次阅读 多人点赞 2017-09-09 22:35:42
    1. 摘要通俗的理解__name__ == '__main__':假如你叫小明.py,在朋友眼中,你...if __name__ == '__main__'的意思是:当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当.py文件以模块形式被导

    1. 摘要

    通俗的理解__name__ == '__main__':假如你叫小明.py,在朋友眼中,你是小明(__name__ == '小明');在你自己眼中,你是你自己(__name__ == '__main__')

    if __name__ == '__main__'的意思是:当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。


    2. 程序入口

    对于很多编程语言来说,程序都必须要有一个入口,比如C,C++,以及完全面向对象的编程语言Java,C#等。如果你接触过这些语言,对于程序入口这个概念应该很好理解,C,C++都需要有一个main函数作为程序的入口,也就是程序的运行会从main函数开始。同样,Java,C#必须要有一个包含Main方法的主类,作为程序入口。

    而Python则不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口。

    一个Python源码文件(.py)除了可以被直接运行外,还可以作为模块(也就是库),被其他.py文件导入。不管是直接运行还是被导入,.py文件的最顶层代码都会被运行(Python用缩进来区分代码层次),而当一个.py文件作为模块被导入时,我们可能不希望一部分代码被运行。

    2.1 一个.py文件被其他.py文件引用

    假设我们有一个const.py文件,内容如下:

    PI = 3.14
    
    def main():
        print("PI:", PI)
    
    main()
    
    # 运行结果:PI: 3.14

    现在,我们写一个用于计算圆面积的area.py文件,area.py文件需要用到const.py文件中的PI变量。从const.py中,我们把PI变量导入area.py:

    from const import PI
    
    def calc_round_area(radius):
        return PI * (radius ** 2)
    
    def main():
        print("round area: ", calc_round_area(2))
    
    main()
    
    '''
    运行结果:
    PI: 3.14
    round area:  12.56
    '''

    2.2 修改const.py,添加if __name__ == "__main__"

    我们看到const.py中的main函数也被运行了,实际上我们不希望它被运行,因为const.py提供的main函数只是为了测试常量定义。这时if __name__ == '__main__'派上了用场,我们把const.py改一下,添加if __name__ == "__main__"

    PI = 3.14
    
    def main():
        print("PI:", PI)
    
    if __name__ == "__main__":
        main()

    运行const.py,输出如下:

    PI: 3.14

    运行area.py,输出如下:

    round area:  12.56

    如上,我们可以看到if __name__ == '__main__'相当于Python模拟的程序入口,Python本身并没有这么规定,这只是一种编码习惯。由于模块之间相互引用,不同模块可能有这样的定义,而程序入口只有一个。到底哪个程序入口被选中,这取决于__name__的值。

    3. __name__

    3.1 __name__反映一个包的结构

    __name__是内置变量,可用于反映一个包的结构。假设我们有一个包a,包的结构如下:

    a
    ├── b
    │   ├── c.py
    │   └── __init__.py
    └── __init__.py

    在包a中,文件c.py,__init__.py,__init__.py的内容都为:

    print(__name__)

    当一个.py文件(模块)被其他.py文件(模块)导入时,我们在命令行执行

    python -c "import a.b.c"

    输出结果:

    a
    a.b
    a.b.c

    由此可见,__name__可以清晰地反映一个模块在包中的层次。

    3.2 __name__表示当前模块的名字

    __name__是内置变量,可用于表示当前模块的名字。我们直接运行一个.py文件(模块)

    python a/b/c.py

    输出结果:

    __main__

    由此我们可知:如果一个.py文件(模块)被直接运行时,则其没有包结构,其__name__值为__main__,即模块名为__main__

    所以,if __name__ == '__main__'的意思是:当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。


    4. __main__.py文件与python -m

    Python的-m参数用于将一个模块或者包作为一个脚本运行,而__main__.py文件相当于是一个包的“入口程序“。

    4.1 运行Python程序的两种方式

    • python xxx.py,直接运行xxx.py文件
    • python -m xxx.py,把xxx.py当做模块运行

    假设我们有一个文件run.py,内容如下:

    import sys
    
    print(sys.path)

    我们用直接运行的方式启动

    python run.py

    输出结果(为了说明问题,输出结果只截取了重要部分,下同):

    ['/home/huoty/aboutme/pythonstudy/main', ...]

    然后以模块的方式运行:

    python -m run.py

    输出内容

    ['', ...]
    /usr/bin/python: No module named run.py

    由于输出结果只列出了关键的部分,应该很容易看出他们之间的差异:

    • 直接运行方式是把run.py文件所在的目录放到了sys.path属性中

    • 以模块方式运行是把你输入命令的目录(也就是当前工作路径),放到了 sys.path 属性中。

    以模块方式运行还有一个不同的地方:多出了一行No module named run.py的错误。实际上以模块方式运行时,Python先对run.py执行一遍 import,所以print(sys.path)被成功执行,然后Python才尝试运行run.py模块,但是在path变量中并没有run.py这个模块,所以报错。正确的运行方式,应该是python -m run

    4.2 __main__.py的作用

    仍然先看例子,假设我们有如下一个包package:

    package
    ├── __init__.py
    └── __main__.py

    其中,文件__init__.py的内容

    import sys
    
    print("__init__")
    print(sys.path)

    其中,文件__main__.py的内容

    import sys
    
    print("__main__")
    print(sys.path)

    接下来,我们运行这个package,使用python -m package运行,输出结果:

    __init__
    ['', ...]
    
    __main__
    ['', ...]

    使用python package运行,输出结果:

    __main__
    ['package', ...]

    总结一下

    • 当加上-m参数时,Python会把当前工作目录添加到sys.path中;而不加-m时,Python则会把脚本所在目录添加到sys.path中。

    • 当加上-m参数时,Python会先将模块或者包导入,然后再执行。

    • __main__.py文件是一个包或者目录的入口程序。不管是用python package还是用python -m package运行,__main__.py文件总是被执行。

    5. 参考文章

    1. Python 中的 if name == ‘main’ 该如何理解

    展开全文
  • Python中if __name__ == '__main__',__init__和self 的解析

    万次阅读 多人点赞 2018-09-03 10:32:21
    文章主要包括2部分内容,分别是if __name__ == '__main__'的解析和__init__与self的解析。 目录 1 if __name__ == '__main__' 1.1 摘要 1.2程序入口 1.2.1一个.py文件被其他.py文件引用 1.2.2修改const.py,...

    文章主要包括2部分内容,分别是if __name__ == '__main__'的解析和__init__与self的解析。

    目录

    1 if __name__ == '__main__'

    1.1 摘要

    1.2 程序入口

    1.2.1 一个.py文件被其他.py文件引用

    1.2.2 修改const.py,添加if __name__ == "__main__"

    2 __init__与self

    2.1 Python中self的含义

    2.2 Python中为何要有self

    2.3 首先来看一下__init__()和self对象

    2.4 如果没有在__init__中初始化对应的实例变量的话,导致后续引用实例变量会出错

    2.5 在函数中,使用对应的变量,虽然代码是可以运行的,但是实际上使用的,不是实例中的变量

    3 参考文献


    1 if __name__ == '__main__'

    1.1 摘要

    通俗的理解__name__ == '__main__':假如你叫小明.py,在朋友眼中,你是小明(__name__ == '小明');在你自己眼中,你是你自己(__name__ == '__main__')

    if __name__ == '__main__'的意思是:当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。

    1.2 程序入口

    对于很多编程语言来说,程序都必须要有一个入口,比如C,C++,以及完全面向对象的编程语言Java,C#等。如果你接触过这些语言,对于程序入口这个概念应该很好理解,C,C++都需要有一个main函数作为程序的入口,也就是程序的运行会从main函数开始。同样,Java,C#必须要有一个包含Main方法的主类,作为程序入口。

    而Python则不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口

    一个Python源码文件(.py)除了可以被直接运行外,还可以作为模块(也就是库),被其他.py文件导入。不管是直接运行还是被导入,.py文件的最顶层代码都会被运行(Python用缩进来区分代码层次),而当一个.py文件作为模块被导入时,我们可能不希望一部分代码被运行。

    1.2.1 一个.py文件被其他.py文件引用

    假设我们有一个const.py文件,内容如下:

    PI = 3.14
    
    def main():
        print("PI:", PI)
    
    main()
    
    # 运行结果:PI: 3.14

     现在,我们写一个用于计算圆面积的area.py文件,area.py文件需要用到const.py文件中的PI变量。从const.py中,我们把PI变量导入area.py:

    from const import PI
    
    def calc_round_area(radius):
        return PI * (radius ** 2)
    
    def main():
        print("round area: ", calc_round_area(2))
    
    main()
    
    '''
    运行结果:
    PI: 3.14
    round area:  12.56
    '''

    1.2.2 修改const.py,添加if __name__ == "__main__"

    我们看到const.py中的main函数也被运行了,实际上我们不希望它被运行,因为const.py提供的main函数只是为了测试常量定义。这时if __name__ == '__main__'派上了用场,我们把const.py改一下,添加if __name__ == "__main__"

    PI = 3.14
    
    def main():
        print("PI:", PI)
    
    if __name__ == "__main__":
        main()

    运行const.py,输出如下:

    PI: 3.14

    运行area.py,输出如下:

    round area:  12.56

    如上,我们可以看到if __name__ == '__main__'相当于Python模拟的程序入口,Python本身并没有这么规定,这只是一种编码习惯。由于模块之间相互引用,不同模块可能有这样的定义,而程序入口只有一个。到底哪个程序入口被选中,这取决于__name__的值。


    2 __init__与self

    2.1 Python中self的含义

    self,英文单词意思很明显,表示自己,本身。python的self,是个对象(Object),是当前类的实例。

    2.2 Python中为何要有self

    那就是:

    在类的代码(函数)中,需要访问当前的实例中的变量和函数的,即,访问Instance中的:

    • 对应的变量(属性,property):Instance.ProperyNam,去读取之前的值和写入新的值
    • 调用对应函数(function):Instance.function(),即执行对应的动作

    -> 而需要访问实例的变量和调用实例的函数,当然需要对应的实例Instance对象本身

    -> 而Python中就规定好了,函数的第一个参数,就必须是实例对象本身,并且建议,约定俗成,把其名字写为self

    -> 所以,我们需要self

    而如果没有用到self,即代码中,去掉self后,那种写法所使用到的变量,实际上不是你所希望的,不是真正的实例中的变量和函数,而是的访问到了其他部分的变量和函数了。甚至会由于没有合适的初始化实例变量,而导致后续无法访问的错误。

    下面,就通过代码,来演示,如果去掉self,或者没有合理的使用self,会出现哪些错误。

    2.3 首先来看一下__init__()和self对象 

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
     
    class Person(object):
        def __init__(self, name, lang, website):
            self.name = name
            self.lang = lang
            self.website = website
     
            print('self: ', self)
            print('type of self: ', type(self))
    '''
    未实例化时,运行程序,构造方法没有运行
    '''
     
    p = Person('Tim', 'English', 'www.universal.com')   
     
    '''实例化后运行的结果
    self:  <__main__.Person object at 0x00000000021EAF98>
    type of self:  <class '__main__.Person'>
    '''

    可以看出self为实例变量p,是一个Person类型的对象。

    class Dog(object):       
        def __init__(self,name,dog_type):
            self.name = name
            self.type = dog_type
       
        def sayhi(self):
            print("hello,I am a dog, my name is ",self.name)
       
       
    d = Dog('LiChuang',"京巴")            # 实例化
    d.sayhi()

    以下是d = Dog('LiChuang',"京巴")实例化的示意图:

    2.4 如果没有在__init__中初始化对应的实例变量的话,导致后续引用实例变量会出错

    如下代码,完整的演示了,如果没有在类Class的最初的__init__函数中,正确的初始化实例变量,则会导致后续没有变量可用,因而出现AttributeError的错误:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
     
    name = 'whole global name'
    '''
    注:此处全局的变量名,写成name,只是为了演示而用
    实际上,好的编程风格,应该写成gName之类的名字,
    以表示该变量是Global的变量
    '''
     
    class Person(object):
        def __init__(self, newPersonName):
            # self.name = newPersonName
            '''
            如果此处不写成self.name
            那么此处的name,只是__init__函数中的局部临时变量name而已
            和全局中的name,没有半毛钱关系
            '''
            name = newPersonName
            '''
            此处只是为了代码演示,而使用了局部变量name,
            不过需要注意的是,此处很明显,由于接下来的代码也没有利用到此处的局部变量name
            则就导致了,此处的name变量,实际上被浪费了,根本没有利用到
            '''
        def sayYourName(self):
            '''
            此处由于找不到实例中的name变量,所以会报错:
            AttributeError: Person instance has no attribute 'name'
            '''
            print('My name is %s' %self.name)
     
    def selfAndInitDemo():
        personInstance = Person('Tim')
        personInstance.sayYourName()
     
    if __name__ == '__main__':
        selfAndInitDemo()
     
     
    '''  未使用self.name时抛异常
    Traceback (most recent call last):
      File "E:/python14_workspace/s14/day06/test_1.py", line 18, in <module>
        selfAndInitDemo()
      File "E:/python14_workspace/s14/day06/test_1.py", line 15, in selfAndInitDemo
        personInstance.sayYourName()
      File "E:/python14_workspace/s14/day06/test_1.py", line 11, in sayYourName
        print('My name is %s' %self.name)
    AttributeError: 'Person' object has no attribute 'name'
    '''

    从上述代码可见,由于在类的初始化(实例化)的__init__函数中,没有给self.name设置值,使得实例中,根本没有name这个变量,导致后续再去访问self.name,就会出现AttributeError的错误了。

    对应的,如果写成self.name,则意思就正确了,就是初始化的时候,给实例中新增加,并且正常设置了正确的值newPersionName了,所以后续再去通过self.name,就可以访问到,当前实例中正确的变量name了。

    相应的正确写法的代码如下:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
     
    name = 'whole global name'
    '''
    注:此处全局的变量名,写成name,只是为了演示而用
    实际上,好的编程风格,应该写成gName之类的名字,
    以表示该变量是Global的变量
    '''
     
    class Person(object):
        def __init__(self, newPersonName):
            self.name = newPersonName
            '''
            此处正确的,通过访问self.name的形式,实现了:
                1.给实例中,增加了name变量
                2.并且给name赋了初值,为newPersionName
            '''
        def sayYourName(self):
            '''
            此处由于开始正确的初始化了self对象,使得其中有了name变量,
            所以此处可以正确访问了name值了
            '''
            print('My name is %s' %self.name)
     
    def selfAndInitDemo():
        personInstance = Person('Tim')
        personInstance.sayYourName()
     
    if __name__ == '__main__':
        selfAndInitDemo()
     
     
    '''My name is Tim'''

    2.5 在函数中,使用对应的变量,虽然代码是可以运行的,但是实际上使用的,不是实例中的变量

    有时候,虽然你写的代码,可以运行,但是使用到的变量,由于没有加self,实际上是用到的不是实例的变量,而是其他的变量。

    此类问题,主要和Python中的变量的作用域有关,但是此处例子中,也和是否使用self有关:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
     
    name = 'whole global name'
    '''
    注:此处全局的变量名,写成name,只是为了演示而用
    实际上,好的编程风格,应该写成gName之类的名字,
    以表示该变量是Global的变量
    '''
     
    class Person(object):
        name = 'class global name'
     
        def __init__(self, newPersonName):
            # self.name = newPersonName
            '''
            此处,没有使用self.name
            而使得此处的name,实际上仍是局部变量name
            虽然此处赋值了,但是后面没有被利用到,属于被浪费了的局部变量name
            '''
            name = newPersonName
        def sayYourName(self):
            '''
            此处,之所以没有像之前一样出现:
            AttributeError: Person instance has no attribute 'name'
            那是因为,虽然当前的实例self中,没有在__init__中初始化对应的name变量,实例self中没有对应的name变量
            但是由于实例所对应的类Person,有对应的name变量,所以也是可以正常执行代码的
            对应的,此处的self.name,实际上是Person.name
            '''
            print('My name is %s' %self.name)
            print('Name within class Person is actually the global name: %s' %name)
            print("Only access Person's name via Person.name = %s" %(Person.name))
     
    def selfAndInitDemo():
        personInstance = Person('Tim')
        personInstance.sayYourName()
        print('whole global name is %s' %name)
     
    if __name__ == '__main__':
        selfAndInitDemo()
     
     
    '''
    My name is class global name
    Name within class Person is actually the global name: whole global name
    Only access Person's name via Person.name = class global name
    whole global name is whole global name
    '''

    其中,可见,此处开始__init__中,没有给self实例初始化对应的name,

    而后面的函数sayYourName中,虽然可以调用到self.name而没有出现AttributeError错误,

    但是实际上此处的值,不是所期望的,传入的name,即"Tim",而是类中的name的值,即"class global name"。

    3 参考文献

    【1】如何简单地理解Python中的if __name__ == '__main__'

    【2】Python类中的__init__() 和 self 的解析

    展开全文
  • Python中__repr____str__区别

    万次阅读 多人点赞 2016-12-14 23:21:25
    看下面的例子就明白了class Test(object):... def __init__(self, value='hello, world!'): self.data = value>>> t = Test() >>> t <__main__.Test at 0x7fa91c307190> >>> print t <__main__.Test object at 0x7fa91
  • Python中的__init__()和__call__()函数

    万次阅读 多人点赞 2017-04-20 11:31:07
    __init__()和__call__()就是class很有用的两类特殊的函数。 __init__() 在Python中,__init__()函数的意义等同于类的构造器(同理,__del__()等同于类的析构函数)。因此,__init__()方法的作用是创建一个类的...
  • if __name__ == '__main__' 如何正确理解?

    万次阅读 多人点赞 2018-03-10 10:47:57
    在大多数编排得好一点的脚本或者程序里面都有这段if __name__ == 'main': ,虽然一直知道他的作用,但是一直比较模糊,收集资料详细理解之后与大家分享。 1、这段代码的功能 一个python的文件有两种使用的方法,第...
  • 5分钟学会MySQL-  "this is incompatible with sql_mode=only_full_group_by"错误解决方案   前言:  一、原理层面  这个错误发生在mysql 5.7 版本及以上版本会出现的问题...
  • vsftpd 配置:chroot_local_user与chroot_list_enable详解

    万次阅读 多人点赞 2015-01-05 09:24:38
    很多情况下,我们希望限制ftp用户只能在其主目录下(root dir)下活动,不允许他们跳出主目录之外浏览服务器上的其他目录,这时候我就需要使用到chroot_local_user,chroot_list_enable,chroot_list_file这三个选项了...
  • Python super().__init__()测试及理解

    万次阅读 多人点赞 2019-02-24 13:20:17
    Python3 super().__init__()含义 测试一、我们尝试下面代码,没有super(A, self).__init__()时调用A的父类Root的属性和方法(方法里不对Root数据进行二次操作) class Root(object): def __init__(self): self.x=...
  • python中super().__init__()

    万次阅读 多人点赞 2020-03-01 21:55:12
    super().__init__() 1、子类构造函数调用super().__init__()1.1、第一个直接继承父类,可以调用name1.2、第二个继承自父类,覆盖初始化化def init,增加属性age,不能调用name属性1.3、第三个继承自父类,覆盖...
  • emplace_back() 和 push_back 的区别

    万次阅读 多人点赞 2016-09-17 00:05:42
    emplace_back()
  • GCC在C语言中内嵌汇编 asm __volatile__

    万次阅读 多人点赞 2012-11-26 22:20:05
    在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量... __asm__ __volatile__("hlt"); "__asm__"表示后面的代码为内嵌汇编,"as
  • Sklearn-train_test_split随机划分训练集和测试集

    万次阅读 多人点赞 2017-02-05 15:06:15
    sklearn.model_selection.train_test_split随机划分训练集和测试集 官网文档:...
  • Python中的if __name__ == '__main__'

    万次阅读 多人点赞 2018-10-01 07:22:35
    在具体说明if __name__ == '__main__'功能前,先从一个简单的实例直观上感受一下。 # const.py PI = 3.14 def train(): print("PI:", PI) train() # area.py from const import PI def calc_round_area...
  • C语言__attribute__的使用

    万次阅读 多人点赞 2019-06-17 22:54:03
    一、介绍 GNU C的一大特色就是__attribute__机制。__attribute__可以设置函数属性(Function ...__attribute__书写特征是:__attribute__前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__att...
  • Python中__init__的用法和理解

    万次阅读 多人点赞 2018-09-23 16:35:25
    在Python中定义类经常会用到__init__函数(方法),首先需要理解的是,两个下划线开头的函数是声明该属性为私有,不能在类的外部被使用或访问。而__init__函数(方法)支持带参数类的初始化,也可为声明该类的属性...
  • mysql 5.7版本默认的sql配置是:sql_mode=“ONLY_FULL_GROUP_BY”,这个配置严格执行了"SQL92标准"。 很多从5.6升级到5.7时,为了语法兼容,大部分都会选择调整sql_mode,使其保持跟5.6一致,为了尽量兼容程序。 二、...
  • 成功解决TypeError: __init__() got an unexpected keyword argument 'n_iterations' 目录 解决问题 解决思路 解决方法 解决问题 TypeError: __init__() got an unexpected keyword argument 'n_...
  • python def __init__(self, name等多参数), def __init__(self)

    万次阅读 多人点赞 2018-10-08 20:19:22
    __init__(self) 初始化,__new__实例化方法,两者执行的顺序,先有实例,才能初始化。 之前一直对__init__(self)里面的参数很迷茫,一会这个地方看到别人这么写,一会看到别人那么写,自己也不知道,到底怎么回事,...
  • C语言中的__FILE____LINE____func__等预定义跟踪调试

    万次阅读 多人点赞 2017-11-24 22:46:31
    标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程...__DATE__转换的日历日期,表示为Mmm dd yyyy 形式的字符串常量,Mmm是由asctime
  • 真正有效解决ONLY_FULL_GROUP_BY的问题

    万次阅读 多人点赞 2019-09-19 17:26:17
    有效解决ONLY_FULL_GROUP_BY的问题 问题描述 报错 如上图 在mysql 5.7版本下可能会报如下错误 Error Code: 1055. Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column ...
  • python中__name__的意义以及作用

    万次阅读 多人点赞 2017-09-24 17:06:27
    首先定义了一个test.py的文件,然后再定义一个函数,并在函数定义后直接运行:test.py... if __name__ == '__main__': print('I am in my domain,my name is %s' % __name__) else: print('Someone else calls me!,
  • 关于_CRT_SECURE_NO_WARNINGS

    万次阅读 2020-06-28 19:44:44
    写MFC时无论在预处理器处添加_CRT_SECURE_NO_WARNINGS还是在文件中定义_CRT_SECURE_NO_WARNINGS都还是报错,之后查到添加到stdafx.h文件中就好了,在这里记录一下。
  • Python-__getattr____getattribute__

    万次阅读 2020-06-25 09:22:32
    文章目录\_\_getattr_\_()解释说明\_\_getattribute\_解释说明使用案例 __getattr__() 解释说明 定义了__getattr__(),当访问object不存在的属性时会调用该方法 不定义访问不存在的属性时会报 AttributeError class ...
  • cross_val_score的 scoring参数值解析

    万次阅读 多人点赞 2018-09-24 20:56:07
    一般我们在模型训练过程中,...sklearn.model_selection 的 cross_val_score 方法来计算模型的得分 scores = cross_val_score(clf, iris.data, iris.target, cv=5,scoring='accuracy') 我们看到这里有个参数 sc...
  • __DATE__ __TIME__

    万次阅读 2018-07-31 15:41:57
    //__FILE__ 包含当前程序文件名的字符串 //__LINE__ 表示当前行号的整数 //__DATE__ 包含当前日期的字符串 //__STDC__ 如果编译器遵循ANSI C标准,它就是个非零值 //__TIME__ 包含当前时间的字符串 //__...
  • __LINE__ __FUNCTION__用法

    万次阅读 2018-08-20 13:59:01
    __LINE__, 行号 __FUNCTION__ 函数 用法:可以用于程序错误时打印错误位置 printf("行号:%d 函数名:%s \n", __LINE__, __FUNCTION__);
  • AttributeError: module 'tensorflow' has no attribute '__version__' 一看,懵逼了,啥,tensorflow么有__version__方法,打开Python解释器看下, import tensorflow tensorflow.__version__ 我去,还真没...
  • cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso

    万次阅读 多人点赞 2018-06-28 15:56:51
    ed2k://|file|cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso|3420557312|B58548681854236C7939003B583A8078|/文件: D:\迅雷下载\cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso大小: 3420557312 字节...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,300,776
精华内容 3,720,310
关键字:

_