Python 高级知识点,如 ==
和 is 的区别,位运算。
import 导入模块
import 搜索路径
1 | >>> import sys |
路径搜索
- 从上面列出的目录里依次查找要导入的模块文件
''
表示当前路径
新增导入路径
1 | sys.path.append('/home/itcast/xxx') |
重新导入模块
模块被导入后,import module
不能重新导入模块,重新导入需用
1 | from imp import reload |
== 和 is
1 | 1,2,3] a = [ |
- is 是比较两个引用是否指向了同一个对象(引用比较)也被叫做同一性运算符,这个运算符比较判断的是对象间的唯一身份标识,也就是id是否相同。
- == 用来比较判断两个对象的 value (值)是否相等
- 类似于 Java 同样存在,比较引用还是比较真实值的问题
- Python 在为数字分配内存时,按照数字的内容来分配内存,即 a = 5;b = 5时,Python 只对数字 5 分配一块内存空间,而不是对变量 a 和 b 各分配一块内存;(在 Python 交互式界面有内存池缓存机制,只适用于
-5~256
,在 Python 脚本编程中则没有这个限制)
1)Python 中一切都是对象;
2)Python 中 None 是唯一的;每个对象包含3个属性,id,type,value
- id 就是对象地址,可以通过内置函数 id() 查看对象引用的地址。
- type 就是对象类型,可以通过内置函数 type() 查看对象的类型。
- value 就是对象的值。
如下脚本的输出会是什么(非 Python 交互式环境)?
1 | a = 300 |
正确答案是 True。
是不是很惊喜 😏
位运算
&
按位与|
按位或^
按位异或~
按位取反<<
按位左移>>
按位右移
用途: 直接操作二进制、省内存、效率高
<< 按位左移
各二进位全部左移 n 位,高位丢弃,低位补 0
注意事项:
- 左移 1 位相当于乘以 2,可以用于快速计算一个数乘以 2 的 n 次方( 8<<3 等同于 8*2^3)
- 左移可能会改变一个数的正负性
>> 按位右移
各二进位全部右移 n 位,保持符号位不变
x >> n,x 的所有二进制位向右移动 n 位,移出的位删掉,移进的位补符号位 右移不会改变一个数的符号
注意事项:
- 右移 1 位相当于除以 2
- x 右移 n 位就相当于除以 2 的 n 次方,用途:快速计算一个数除以 2 的 n 次方(8>>3 等同于 8/2^3)
& 按位与
全 1 才 1 否则 0 :只有对应的两个二进位均为 1 时,结果位才为 1,否则为 0
| 按位或
有 1 就 1:只要对应的二个二进位有一个为 1 时,结果位就为 1,否则为 0
^ 按位异或
不同为 1:当对应的二进位相异(不相同)时,结果为 1,否则为 0
- 任何数和 1 进行 & 操作,得到这个数的最低位。即:
数字&1
= 数字的二进制形式的最低位 - 位运算优先级
私有化
xx
:公有变量_x
:单前置下划线,私有化属性或方法,from somemodule import *
禁止导入,类对象和子类可以访问__xx
:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)__xx__
:双前后下划线,用户名字空间的魔法对象或属性。例如:__init__
,不要自己发明这样的名字xx_
:单后置下划线,用于避免与 Python 关键词的冲突
1 | class Person(object): |
- 运行结果
1 | $ python private.py |
可以看到 Python 对类的私有属性进行了重整,__age
变成了 _Person__age
,因此无法直接获取到。
总结
- 父类中属性名为
__xx
的,子类不继承,子类不能访问 - 如果在子类中向
__xx
赋值,那么会在子类中定义的一个与父类相同名字的属性 _xx
的变量、函数、类在使用from xxx import *
时都不会被导入
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法对参数进行检查,于是我们可以使用 get、set 方法来对属性进行设置和检查。
1 | class Money(object): |
但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。
有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?
Python 内置的 @property
装饰器就是负责把一个方法变成属性调用的:
1 | class Money(object): |
@property
的实现比较复杂,我们先考察如何使用。把一个 getter 方法变成属性,只需要加上 @property
就可以了,此时,@property
本身又创建了另一个装饰器 @money.setter
,负责把一个 setter 方法变成属性赋值,于是,我们就拥有一个可控的属性操作:
1 | >>> from private import Money |
注意到这个神奇的 @property
,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过 getter 和 setter 方法来实现的。
@property
成为属性函数,可以对属性赋值时做必要的检查,并保证代码的清晰短小,主要有 2 个作用:
- 将方法转换为只读
- 重新实现一个属性的设置和读取方法,可做边界判定