㈠ python语言中作用域怎么理解
命名空间 是从命名到对象的映射。当前命名空间主要是通过 Python 字典实现的,不过通常不关心具体的实现方式(除非出于性能考虑),以后也有可能会改变其实现方式。以下有一些命名空间的例子:内置命名(像 abs() 这样的函数,以及内置异常名)集,模块中的全局命名,函数调用中的局部命名。某种意义上讲对象的属性集也是一个命名空间。关于命名空间需要了解的一件很重要的事就是不同命名空间中的命名没有任何联系,例如两个不同的模块可能都会定义一个名为 maximize 的函数而不会发生混淆-用户必须以模块名为前缀来引用它们。
顺便提一句,我称 Python 中任何一个“.”之后的命名为 属性 --例如,表达式 z.real 中的 real 是对象 z 的一个属性。严格来讲,从模块中引用命名是引用属性:表达式 modname.funcname 中,modname 是一个模块对象,funcname 是它的一个属性。因此,模块的属性和模块中的全局命名有直接的映射关系:它们共享同一命名空间![1]
属性可以是只读过或写的。后一种情况下,可以对属性赋值。你可以这样做: modname.the_answer = 42 。可写的属性也可以用 del 语句删除。例如: del modname.the_answer 会从 modname 对象中删除 the_answer 属性。
不同的命名空间在不同的时刻创建,有不同的生存期。包含内置命名的命名空间在 Python 解释器启动时创建,会一直保留,不被删除。模块的全局命名空间在模块定义被读入时创建,通常,模块命名空间也会一直保存到解释器退出。由解释器在最高层调用执行的语句,不管它是从脚本文件中读入还是来自交互式输入,都是 __main__ 模块的一部分,所以它们也拥有自己的命名空间(内置命名也同样被包含在一个模块中,它被称作 builtins )。
当调用函数时,就会为它创建一个局部命名空间,并且在函数返回或抛出一个并没有在函数内部处理的异常时被删除。(实际上,用遗忘来形容到底发生了什么更为贴切。)当然,每个递归调用都有自己的局部命名空间。
作用域 就是一个 Python 程序可以直接访问命名空间的正文区域。这里的直接访问意思是一个对名称的错误引用会尝试在命名空间内查找。尽管作用域是静态定义,在使用时他们都是动态的。每次执行时,至少有三个命名空间可以直接访问的作用域嵌套在一起:
㈡ Python中类的定义规是什么
类的概念:
类 Class: 用来描述具体相同的属性和方法的对象的集合。定义了该集合中每个对象所共有的属性和方法。对象是类的示例。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
实例变量:定义在方法中的变量,只作用于当前实例的类。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关数据。
方法:类中定义的函数。在类内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。
构造函数:即__init()__,特殊的方法,在对象创建的时候被自动调用。
析构函数:即__del()__,特殊的方法,在对象被销毁时被自动调用。
实例化:创建一个类的实例,类的具体对象。就是将创建的类赋值给另一个变量。理解为赋值即可,a = class(),这个过程,就叫做实例化
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其 进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
————————————————
原文链接:https://blog.csdn.net/f156207495/article/details/81166252
网页链接
㈢ Python 中的import 机制
解释器 在执行语句时,遵循作用域原则。因为这和作用域有关系, 如果在顶层导入模块,此时它的作用域是全局的;如果在函数内部导入了模块,那它的作用域只是局部的 ,不能被其它函数使用。如果其它函数也要用到这个模块,还需要再次导入比较麻烦。
在用import语句导入模块时最好按照这样的顺序:
绝对路径 就是文件的真正存在的路径,是指从硬盘的根目录(盘符)开始,进行一级级目录指向文件。
相对路径 就是以当前文件为基准进行一级级目录指向被引用的资源文件。
以下是常用的表示当前目录和当前目录的父级目录的标识符
形如from moleB import ClassB语句,根据Python内部import机制,执行细分步骤:
总结:from moleB import ClassB有两个过程,先from mole,后import ClassB。
当然将moleA.py语句 from moleB import ClassB改为:import moleB,将在第二次执行moleB.py语句from moleA import ClassA时报错:ImportError: cannot import name ‘classA’
在一个文件下同时有 init .py文件、和其他模块文件时,该文件夹即看作一个包(package)。包的导入 和模块导入基本一致,只是导入包时,会执行这个 init .py,而不是模块中的语句。
而且,如果只是单纯地导入包【形如:import xxx】,而包的 init .py中有没有明确地的其他初始化操作,则:此包下的模块 是不会被自动导入的。当然该包是会成功导入的,并将包名称放入当前.py的Local命名空间中。
参考文章:
Python中import机制
Python 3.x可能是史上最详解的【导入(import)】
在Python中以绝对路径或者相对路径导入文件的方法
Python的模块引用和查找路径
㈣ python里面变量作用域是什么
变量作用域:python可以直接查找名称到对象的映射(命名空间)的部分。
python有built–in、global、enclosing、local这四种作用域
built–in:内建作用域,包含了内建的变量和关键字。
global:全局作用域,定义在所有函数外,当前模块(.py源文件)的全局变量。
enclosing:闭包函数外的函数(非局部也非全局),比如有一个函数a,a里有另一个函数b,对于b里的变量来说,a中的作用域就是enclosing。
local:局部作用域,脚本最内层,比如函数里。
㈤ 深入探究Python中变量的拷贝和作用域问题
这篇文章主要介绍了Python中变量的拷贝和作用域问题,包括一些赋值、引用问题,以及相关函数在Python2和3版本之间的不同,需要的朋友可以参考下
在
python
中赋值语句总是建立对象的引用值,而不是复制对象。因此,python
变量更像是指针,而不是数据存储区域,
这点和大多数
OO
语言类似吧,比如
C++、java
等
~
1、先来看个问题吧:
在Python中,令values=[0,1,2];values[1]=values,为何结果是[0,[...],2]?
?
1
2
3
4
>>>
values
=
[0,
1,
2]
>>>
values[1]
=
values
>>>
values
[0,
[...],
2]
我预想应当是
?
1
[0,
[0,
1,
2],
2]
但结果却为何要赋值无限次?
可以说
Python
没有赋值,只有引用。你这样相当于创建了一个引用自身的结构,所以导致了无限循环。为了理解这个问题,有个基本概念需要搞清楚。
Python
没有“变量”,我们平时所说的变量其实只是“标签”,是引用。
执行
?
1
values
=
[0,
1,
2]
的时候,Python
做的事情是首先创建一个列表对象
[0,
1,
2],然后给它贴上名为
values
的标签。如果随后又执行
?
1
values
=
[3,
4,
5]
的话,Python
做的事情是创建另一个列表对象
[3,
4,
5],然后把刚才那张名为
values
的标签从前面的
[0,
1,
2]
对象上撕下来,重新贴到
[3,
4,
5]
这个对象上。
至始至终,并没有一个叫做
values
的列表对象容器存在,Python
也没有把任何对象的值复制进
values
去。过程如图所示:
执行
?
1
values[1]
=
values
的时候,Python
做的事情则是把
values
这个标签所引用的列表对象的第二个元素指向
values
所引用的列表对象本身。执行完毕后,values
标签还是指向原来那个对象,只不过那个对象的结构发生了变化,从之前的列表
[0,
1,
2]
变成了
[0,
?,
2],而这个
?
则是指向那个对象本身的一个引用。如图所示:
要达到你所需要的效果,即得到
[0,
[0,
1,
2],
2]
这个对象,你不能直接将
values[1]
指向
values
引用的对象本身,而是需要吧
[0,
1,
2]
这个对象“复制”一遍,得到一个新对象,再将
values[1]
指向这个复制后的对象。Python
里面复制对象的操作因对象类型而异,复制列表
values
的操作是
values[:]
#生成对象的拷贝或者是复制序列,不再是引用和共享变量,但此法只能顶层复制
所以你需要执行
?
1
values[1]
=
values[:]
Python
做的事情是,先
dereference
得到
values
所指向的对象
[0,
1,
2],然后执行
[0,
1,
2][:]
复制操作得到一个新的对象,内容也是
[0,
1,
2],然后将
values
所指向的列表对象的第二个元素指向这个复制二来的列表对象,最终
values
指向的对象是
[0,
[0,
1,
2],
2]。过程如图所示:
往更深处说,values[:]
复制操作是所谓的“浅复制”(shallow
),当列表对象有嵌套的时候也会产生出乎意料的错误,比如
?
1
2
3
4
a
=
[0,
[1,
2],
3]
b
=
a[:]
a[0]
=
8
a[1][1]
=
9
问:此时
a
和
b
分别是多少?
正确答案是
a
为
[8,
[1,
9],
3],b
为
[0,
[1,
9],
3]。发现没?b
的第二个元素也被改变了。想想是为什么?不明白的话看下图
正确的复制嵌套元素的方法是进行“深复制”(deep
),方法是
?
1
2
3
4
5
6
import
a
=
[0,
[1,
2],
3]
b
=
.deep(a)
a[0]
=
8
a[1][1]
=
9
2、引用
VS
拷贝:
(1)没有限制条件的分片表达式(L[:])能够复制序列,但此法只能浅层复制。
(2)字典
方法,D.()
能够复制字典,但此法只能浅层复制
(3)有些内置函数,例如
list,能够生成拷贝
list(L)
(4)
标准库模块能够生成完整拷贝:deep
本质上是递归
(5)对于不可变对象和可变对象来说,浅复制都是复制的引用,只是因为复制不变对象和复制不变对象的引用是等效的(因为对象不可变,当改变时会新建对象重新赋值)。所以看起来浅复制只复制不可变对象(整数,实数,字符串等),对于可变对象,浅复制其实是创建了一个对于该对象的引用,也就是说只是给同一个对象贴上了另一个标签而已。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
L
=
[1,
2,
3]
D
=
{'a':1,
'b':2}
A
=
L[:]
B
=
D.()
print
"L,
D"
print
L,
D
print
"A,
B"
print
A,
B
print
"--------------------"
A[1]
=
'NI'
B['c']
=
'spam'
print
"L,
D"
print
L,
D
print
"A,
B"
print
A,
B
L,
D
[1,
2,
3]
{'a':
1,
'b':
2}
A,
B
[1,
2,
3]
{'a':
1,
'b':
2}
--------------------
L,
D
[1,
2,
3]
{'a':
1,
'b':
2}
A,
B
[1,
'NI',
3]
{'a':
1,
'c':
'spam',
'b':
2}
3、增强赋值以及共享引用:
x
=
x
+
y,x
出现两次,必须执行两次,性能不好,合并必须新建对象
x,然后复制两个列表合并
属于复制/拷贝
x
+=
y,x
只出现一次,也只会计算一次,性能好,不生成新对象,只在内存块末尾增加元素。
当
x、y
为list时,
+=
会自动调用
extend
方法进行合并运算,in-place
change。
属于共享引用
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
L
=
[1,
2]
M
=
L
L
=
L
+
[3,
4]
print
L,
M
print
"-------------------"
L
=
[1,
2]
M
=
L
L
+=
[3,
4]
print
L,
M
[1,
2,
3,
4]
[1,
2]
-------------------
[1,
2,
3,
4]
[1,
2,
3,
4]
4、python
从2.x
到3.x,语句变函数引发的变量作用域问题
先看段代码:
?
1
2
3
4
5
6
7
8
9
def
test():
a
=
False
exec
("a
=
True")
print
("a
=
",
a)
test()
b
=
False
exec
("b
=
True")
print
("b
=
",
b)
在
python
2.x
和
3.x
下
你会发现他们的结果不一样:
?
1
2
3
4
5
6
7
2.x:
a
=
True
b
=
True
3.x:
a
=
False
b
=
True
这是为什么呢?
因为
3.x
中
exec
由语句变成函数了,而在函数中变量默认都是局部的,也就是说
你所见到的两个
a,是两个不同的变量,分别处于不同的命名空间中,而不会冲突。
具体参考
《learning
python》P331-P332
知道原因了,我们可以这么改改:
?
1
2
3
4
5
6
7
8
9
10
11
12
def
test():
a
=
False
ldict
=
locals()
exec("a=True",globals(),ldict)
a
=
ldict['a']
print(a)
test()
b
=
False
exec("b
=
True",
globals())
print("b
=
",
b)
这个问题在
stackoverflow
上已经有人问了,而且
python
官方也有人报了
bug。。。
具体链接在下面:
http://stackoverflow.com/questions/7668724/variables-declared-in-execed-code-dont-become-local-in-python-3-documentatio
http://bugs.python.org/issue4831
http://stackoverflow.com/questions/1463306/how-does-exec-work-with-locals
㈥ 学习python必备的基础知识
python作为当下最热门的计算机编程语言之一,是许多互联网大厂(如阿里腾讯等)在招聘时会作出要求的能力之一。学好python对于将来大数据方向、云计算方向等物联网时代新兴岗位的学习很有帮助。
想要学习Python,需要掌握的内容还是比较多的,对于自学的同学来说会有一些难度,不推荐自学能力差的人。我们将学习的过程划分为4个阶段,每个阶段学习对应的内容,具体的学习顺序如下:
Python学习顺序:
①Python软件开发基础
掌握计算机的构成和工作原理
会使用Linux常用工具
熟练使用Docker的基本命令
建立Python开发环境,并使用print输出
使用Python完成字符串的各种操作
使用Python re模块进行程序设计
使用Python创建文件、访问、删除文件
掌握import 语句、From…import 语句、From…import* 语句、方法的引用、Python中的包
②Python软件开发进阶
能够使用Python面向对象方法开发软件
能够自己建立数据库,表,并进行基本数据库操作
掌握非关系数据库MongoDB的使用,掌握Redis开发
能够独立完成TCP/UDP服务端客户端软件开发,能够实现ftp、http服务器,开发邮件软件
能开发多进程、多线程软件
③Python全栈式WEB工程师
能够独立完成后端软件开发,深入理解Python开发后端的精髓
能够独立完成前端软件开发,并和后端结合,熟练掌握使用Python进行全站Web开发的技巧
④Python多领域开发
能够使用Python熟练编写爬虫软件
能够熟练使用Python库进行数据分析
招聘网站Python招聘职位数据爬取分析
掌握使用Python开源人工智能框架进行人工智能软件开发、语音识别、人脸识别
掌握基本设计模式、常用算法
掌握软件工程、项目管理、项目文档、软件测试调优的基本方法
想要系统学习,你可以考察对比一下开设有IT专业的热门学校,好的学校拥有根据当下企业需求自主研发课程的能,南京北大青鸟、中博软件学院、南京课工场等都是不错的选择,建议实地考察对比一下。
祝你学有所成,望采纳。