编程语言元类和连接符python的用法
简介
本节简单介绍python语言中元类和连接符的用法。
1 type 元类
3个用法
-
1,判断对象类型
type(2)
int
type(‘a’)
string
-
2, 动态创建类
接收一个类的描述符作为参数,然后返回一个类
type(类名,父类元组(针对继承的场景,可以为空),包含属性的字典(名称和值))
class myclass:
pass
等价与
mySingClass = type('myclass', (), {})
其他例子
Foo = type('Foo', (), {'bar':True})
- 3 type 类工厂
type 是所有object对象的父类
所有对象都继承自object,所有类都继承自type
type可用于动态创建新类的内置函数。
1),如果给定参数,则返回参数的类型
type(1)
<class 'int'>
2),如果给定3个参数 name,bases,dict,它将创建一个新类
name定义类的名称
bases定义基类,即超类
dict定义所有类属性和方法。
clsas MyClass(MySuperClass):
def x(self):
print('x')
与此类相同
def x_function(self):
print('x')
MyClass = type("MyClass", (MySuperClass,), {'x', x_function})
这是可实现collections.namedtuple类的一种方式,例如,它接收类名和属性元组。
2 内建函数
5个常量
True, False, None, Ellipsis 也可写为 … 为了支持类型注释,以及一些花俏的切片支持。
NotImplemented 用于类的运算符定义,使得一个类不支持某些操作。
当您希望告诉python 为此类定义某个运算符时,使用它。
所有的python对象都可用通过在其类中定义的特殊方法添加对所有python运算符的重新定义
+=add + iadd +=
2.1 内建公共函数
print(dir(builtins))
模块属性
-
name # 模块名称
-
doc # 模块文档字符串
-
package # 该模块所属的包,对于顶级模块与__name__对于子模块 它是包的__name__
-
spec # 指模块规范,它包含元数据,模块名称,什么类型以及它是如何创建 加载的
-
loader # 设置为加载模块时导入机制使用的加载器对象,特定在 _frozen_importlib模块定义
-
import # 是定义导入语句如何在python工作的内置函数,在内部是python对import语句所做的
-
debug # #python的全局常量值,总是设置为 True,python在调试模式运行。
-
-o 在优化模式,阻止断言语句做任何事情。
-
debug True False None 是 python真正的常量,不能被更改
-
build_class # 允许类定义接收任意位置和 关键字参数,涉及元类问题
类创建语法只允许传递要继承的基类和元类属性。 新要求是允许可变数量的位置和关键字参数。添加到语言中会有点混乱和复杂。
-
cached # 导入模块时,该属性存储该模块的已编译python __cached的缓存文件路径
2.2 使用type 继承
普通继承方式
class chindFoo(Foo):
pass
使用type方式继承
typeChindFoo = type('typeChindFoo', (Foo,), {'chind_foo':'chindFoo'})
print(typeChindFoo().chind_foo)
'chindFoo'
hasattr(typeChindFoo, "chind_foo")
True
对象属性保存在 class
foo.__class__.__class__
<type 'type'>
2.3 自定义元类
-
metaclass
python创建类时,先在当前定义中寻找 metaclass,如果有就使用 metaclass 创建类
如果没有 ,那么就在 父类中寻找 metaclass, 父类都没有,则在模块中寻找__metaclass__。如果都找不到,python将使用 type创建这个类
在创建类时 把属性都改为大写的
2.4 可hash/散列的 对象
字典的key 应该是hashable。这就是为什么我们总是使用可散列对象作为键。
可散列对象是整数、浮点数、字符串、元组和frozensets
可散列对象也是不可变对象
可变对象: 列表,字典,集合。
2.5 两个列表的加权平均
权重
weight = [0.5, 0.8, 0.7, 0.8, 1.0]
值
values = [10, 20, 10, 10, 30]
平均值
s = sum ( [ weight[i] * values[i] for i in range(len(weight)) ] )/ sum (values)
zip_average = sum ( [ x * y for x,y in zip ( weights , values ) ] ) / sum (values)
打印平均值,
print(zip_average) # 0.825 0.825
2.6 推导式:两个列表的交集
filter 和列表推导式
a = [1,2,3,5,7,9]
b = [2,3,5,6,7,8]
print(filter(lambda x: x in a, b)) # 打印出 [2, 3, 5, 7]
或使用set 计算两个列表的合集
list(set(a) & set(b))
2.7 把字典 按 值排序
有如下列表:
a = ['a','a','c','c','b','c']
# d = dict.fromkeys(a,0)
# or
d = {x:0 for x in a}
print(d)
for ch in a:
d[ch] += 1
print(d)
sorted_d = sorted(d.items(), key=lambda x:x[1], reverse=True)
print(sorted_d)
使用 operator.itemgetter() 排序字典
inventory = {'apple': 3,'banana': 2,'pear': 5,'orange': 1}
s = sorted(inventory.items(), key=operator.itemgetter(0))
print(s)
2.8 查找阿姆斯壮数,阿姆斯特朗数,水仙花数
Armstrong 数,就是n位数的各位数的n次方之和等于该数
例如153可以满足1^3 + 5^3 + 3^3 = 153
def isArmstrong(n):
temp = n
sum = 0
while temp > 0:
sum += (temp % 10)**3
temp //= 10
if n == sum:
return True
return False
n = 1000
print([i for i in range(0,n) if isArmstrong(i)])
# [0, 1, 153, 370, 371, 407]
2.9 求最大公因数
最大公因数(英语:highest common factor,hcf)也称最大公约数(英语:greatest common divisor,gcd)是数学词汇,指能够整除多个整数的最大正整数。
而多个整数不能都为零。
例如8和12的最大公因数为4.
def GCF(n1,n2):
n = min(n1,n2)
while True:
if n1 % n == 0 and n2 % n == 0:
return n
n -= 1
n1 = 80; n2 = 240
print(GCF(n1,n2))
2.10 求最小公倍数
两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。
整数a,b的最小公倍数记为[a,b],同样的,a,b,c的最小公倍数记为[a,b,c],多个整数的最小公倍数也有同样的记号。
def LCM(n1,n2):
n = max(n1,n2)
while True:
if n % n1 == 0 and n % n2 == 0:
return n
n += 1
n1 = 24; n2 = 36
print(LCM(n1,n2))
3 下划线 _ 的用处
Underscore(_)是Python中的唯一字符
3.1 在解释器使用
python自动将解释器中最后一个表达式的值存储到名为 _ 的 特定变量中。
如果需要,还可将这些值分配给其他变量
>>> q2.put_noblock(4)
<Future at 0x1b3359d01c0 state=pending>
>>> _
<Future at 0x1b3359d01c0 state=pending>
>>> 6
6
>>> _
6
3.2 忽略值
如果您不想在解包时使用特定值,只需将该值分配给 _
忽略意味着将值分配给 特殊变量 underscore(_) 我们将值分配给 _
因为在未来的代码中没有使用它
>>> a, _, b = (1,2,3)
>>> _
2
>>> a, *_, b = (1,2,3,4,5,6)
>>> _
[2,3,4,5]
3.3 在循环中使用
在循环中 _ 作为变量:
for _ in range(5):
print(_)
3.4 分隔数字的位数
100万的表示
n = 1_000_000
>>> n = 1_000_000
>>> n
1000000
>>> _ = 1_000_000
>>> _
1000000
二进制
ob_0010
八进制
0o_64
十六进制
>>> 0x_23_ab
9131
3.5 命名
单前下划线
_variable
class T:
def __init__(self):
self._num = 7
单前下划线 不影响 您访问类的变量
但影响从模块导入的名称,如
# funcimport
def func1():
return "test"
def _func2():
return 1000
from funcimport import *
func1() # 可以运行
test
_func2() # 运行失败
NameError name is not defined
但是可以从模块导入使用
import funcimport
funcimport._func2()
1000
单后下划线
variable_
一般可用于python的关键字命名冲突 避免
None_
print_
都是自定义变量,双前下划线
-
__variable
双前下划线变量 将不能被子类继承 和更改
也不能都实例 访问
dir中的列表没有 self.__
只有 Sample.__
列表中有self.__c变量吗?
如果您仔细查看属性列表,您会发现一个名为_Sample__c的属性。这就是名字 mangling。这是为了避免在子类中覆盖变量。
>>> class A:
... def __init__(self):
... self.a = 1
... self._b = 2
... self.__c = 3
>>> aa = A()
>>> aa.a
1
>>> aa._b
2
>>> aa.__c
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute '__c'
如继承了A的 B 也有 __c属性,但是无法访问
>>> dir(B)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__'
, '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__
reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> dir(bb)
['_A__c', '_B__c', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne_
_', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__
', '__weakref__', '_b', 'a', 'a1']
访问的方式必须是特定的 子类名称
>>> bb._B__c
33
>>> bb._A__c
3
内部函数同样的如属性的访问
>>> class C(B):
... def __init__(self):
... self.a = 111
... self._b = 222
... self.__c = 333
... def __innerfunc(self):
... return 322
>>> cc = C()
>>> cc._C__c
333
>>> cc._C__innerfunc
<bound method C.__innerfunc of <__main__.C object at 0x000001B3359D7EE0>>
>>> cc._C__innerfunc()
322
>>> cc.__innerfunc()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute '__innerfunc'
双前后下划线
__variable__
您会发现以双下划线开头和结尾的不同名称。它们被称为魔术方法或dunder 方法。
- 点赞
- 收藏
- 关注作者
评论(0)