编程语言元类和连接符python的用法

举报
码乐 发表于 2023/12/18 10:51:42 2023/12/18
【摘要】 简介本节简单介绍python语言中元类和连接符的用法。 1 type 元类3个用法1,判断对象类型type(2)inttype(‘a’)string2, 动态创建类接收一个类的描述符作为参数,然后返回一个类type(类名,父类元组(针对继承的场景,可以为空),包含属性的字典(名称和值))class myclass: pass等价与 mySingClass = type('myclass'...

简介

本节简单介绍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 方法。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。