牢记python对象的操作方式

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
EMR Serverless StarRocks,5000CU*H 48000GB*H
可观测监控 Prometheus 版,每月50GB免费额度
简介: 【6月更文挑战第20天】在Python中,`hash()`和`is`帮助确定对象的相等性。`dir()`和`vars()`揭示对象的属性和内部表示,`__slots__`优化内存使用。列表和字典结构有不同的内存和性能特性,字典使用哈希表进行快速访问。

简介

默认情况下,python对象不可比较,除非它们相同。is检查内存中的对象引用,而==对于某些类型(如object),实际上是基于id()比较。

哈希值是数据的唯一标识,相同数据的哈希值总是相同,不同数据的哈希值几乎不可能相同。哈希适用于快速查找,如字典和集合。__hash____eq__方法允许自定义对象的哈希行为。

Toroid托瑞德符号.png

2 hash和id 相等

内置函数 hash 和 id 构成了python对象是否相等的支持默认情况下,python对象是不可比较的,除非它们相同。

A = object()
B = object()
A == B
    False

object也被称为哨兵,因为它们可用于准确检查无法复制的值

    __my_sentinel = object()

   def what_was_passed(value=__my_sentinel):
        if value is __my_sentinel:
            print('Nothing was passed.')
        else:
            print(f'You passed a {value!r}.')
    >>> what_was_passed("abc")
        You passed a 'abc'.
    >>> what_was_passed(object())
        You passed a <object object at 0x0000027AF6AD88C0>.
    >>> what_was_passed()
        Nothing was passed.
    >>> what_was_passed(None)
        You passed a None.

python的比较,我们必须了解is关键字python的 is运算符用于检查两个值 是否引用内存相同的确切对象。

将python对象想象位空间中漂浮的盒子,变量,数组索引等被命名位指向这些对象的箭头

而 object 的行为 == 被定义为比较 id,例如这样的类型东西可覆盖 ==

  class object:
       def __eq__(self, other):
              return self is other

实际实现object 是用 C 编写的

  x = [1, 2, 3]
  y = [1, 2, 3]
  x is y
      False
  x == y
      True

我们还没有看过all或者zip还没有看过,但这一切都是为了确保所有给定的列表索引都是相等的。

同样,集合是无序的,所以即使它们的位置也不重要,只有它们的“存在” Python 有了hashes的概念。

任何一段数据的“散列”指的是一个看起来非常随机的预先计算的值,但它可以用来识别那段数据。

3 哈希及其属性

哈希有两个特定的属性:

相同的数据将始终具有相同的哈希值。

即使是非常轻微地更改数据,也会以完全不同的哈希值返回。

这意味着如果两个值具有相同的哈希值,那么它们很可能 * 也具有相同的值。

比较哈希是检查“存在”的一种非常快速的方法。这是字典和集合用来立即在其中查找值的方法:

            >>> hash(42) == hash(42.0) == hash(42+0j)
        True

不可变的容器对象,例如字符串(字符串是字符串的序列)、元组和frozensets,通过组合它们的项目的哈希来生成它们的哈希。

这允许您通过组合函数来为您的类创建自定义哈希hash函数

class Car:
    def __init__(self, color, wheels=4):
        self.color = color
        self.wheels = wheels

    def __hash__(self):
        return hash((self.color, self.wheels))

4 dir 和 vars 一切都是字典对象

所有内容都存储在字典中,vars方法公开了存储在对象和类的变量 一个函数的 的vars方法

    >>> vars(what_was_passed)
        {}

一个类的vars方法

    c = C(x=3)

    >>> vars(C)
    mappingproxy({'__module__': '__main__', 
    'some_cons': 42, 
    '__init__': <function C.__init_
    _ at 0x0000027AF72F4940>, 
    'mth': <function C.mth at 0x0000027AF72F49D0>, 
    '__dict__': <at
    tribute '__dict__' of 'C' objects>, 
    '__weakref__': <attribute '__weakref__' of 'C' objects>, 
    '__doc__': None})
    >>> vars(c)
    {'x': 3}

    c.__class__  # 来自继承
    <class '__main__.C'>

方法(mth和init)实际上作为函数存储在类的字典中 ,函数本身的代码不会因每个对象而改变,只有传递给它的变量会改变。

>>> class C:
...     def function(self, x):
...         print(f'self={self}, x={x}')

>>> c = C()
>>> C.function(c, 5)
self=<__main__.C object at 0x7f90762461f0>, x=5
>>> c.function(5)
self=<__main__.C object at 0x7f90762461f0>, x=5

5 查看objects的所有属性:

    >>> "__class__" in vars(object)
    True
    >>> vars(object).keys()
    dict_keys(['__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__dela
    ttr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__init__', '__new__
    ', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__',
     '__sizeof__', '__dir__', '__class__', '__doc__'])

“方法解析顺序”是如何工作的。简称 MRO, 这是一个对象继承属性和方法的类的列表。

    >>> class A:
    ...     def __init__(self):
    ...         self.x = 'x'
    ...         self.y = 'y'
    ...
    >>> class B(A):
    ...     def __init__(self):
    ...         self.z = 'z'
    ...
    >>> a = A()
    >>> b = B()
    >>> B.mro()
    [<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
    >>> 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__', 'x', 'y', 'z']
    >>> set(dir(b)) - set(dir(a))  # all values in dir(b) that are not in dir(a)
    {'z'}
    >>> vars(b).keys()
    dict_keys(['z'])
    >>> set(dir(a)) - set(dir(object))
    {'x', 'y'}
    >>> vars(a).keys()
    dict_keys(['x', 'y'])

因此,每一级继承都会将较新的方法添加到dir列表中,并dir在子类上显示在其方法解析顺序中找到的所有方法。

这就是 Python 在 REPL 中建议方法完成的方式:

class A:
    x = 'x'
class B(A):
    y = 'y'
b = B()
b.   # 两次 tab 键  。???
    b.x  b.y   # 自动

slots 它只允许其中定义的内容 被类实现。 如果对比 go 的接口,可以类型理解,在go接口中如果没有实现,则编译检查报错。 在python中如果实现超过 slots 定义,则报错。

这是 Python 具有的一种奇怪/有趣的行为:

object 默认具有 slots, 也支持自定义内容。

>>> x = object()   
>>> x.f = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'f'
>>> class A:   
...     x = 1
...
>>> a  = A()
>>> a.f = 5

这就是hash用武之地。首先,让我复制我自己的类list和object在我自己的类中显示的行为:

>>> class C:
...     __slots__ = ()
...
>>> c = C()
>>> c.foo = 5
AttributeError: 'C' object has no attribute 'foo'

6 python的存储数据方式

字典将更多使用内存,列表结构,本质上类型python的元组,结构具有固定大小,内存更少。

这两种方式通过两个对象属性 dictslots

通常所有实例属性 self.foo 都存储在dict字典
除非定义 slots属性,这样对象只能具有恒定的指定的属性
定义了 slots将不会加载 dict

如下 list 的内置函数:

 vars(list)
    mappingproxy({'__repr__': <slot wrapper '__repr__' of 'list' objects>, '__hash__': None, '__getattribute__': <slot wrapper '__getattribute__' of 'list' objects>, '__lt__': <slot wrapper '__lt__' of 'list' objects>, ...)

    __repr__:<slot wrapper '__repr__' of 'list' objects>

7 清晰一些的显示 list 结构:

__hash__:None
__getattribute__:<slot wrapper '__getattribute__' of 'list' objects>
__lt__:<slot wrapper '__lt__' of 'list' objects>
__le__:<slot wrapper '__le__' of 'list' objects>
__eq__:<slot wrapper '__eq__' of 'list' objects>
__ne__:<slot wrapper '__ne__' of 'list' objects>
__gt__:<slot wrapper '__gt__' of 'list' objects>
__ge__:<slot wrapper '__ge__' of 'list' objects>
__iter__:<slot wrapper '__iter__' of 'list' objects>
__init__:<slot wrapper '__init__' of 'list' objects>
__len__:<slot wrapper '__len__' of 'list' objects>
__getitem__:<method '__getitem__' of 'list' objects>
__setitem__:<slot wrapper '__setitem__' of 'list' objects>
__delitem__:<slot wrapper '__delitem__' of 'list' objects>
__add__:<slot wrapper '__add__' of 'list' objects>
__mul__:<slot wrapper '__mul__' of 'list' objects>
__rmul__:<slot wrapper '__rmul__' of 'list' objects>
__contains__:<slot wrapper '__contains__' of 'list' objects>
__iadd__:<slot wrapper '__iadd__' of 'list' objects>
__imul__:<slot wrapper '__imul__' of 'list' objects>
__new__:<built-in method __new__ of type object at 0x00007FFE87DA1AF0>
__reversed__:<method '__reversed__' of 'list' objects>
__sizeof__:<method '__sizeof__' of 'list' objects>
clear:<method 'clear' of 'list' objects>
copy:<method 'copy' of 'list' objects>
append:<method 'append' of 'list' objects>
insert:<method 'insert' of 'list' objects>
extend:<method 'extend' of 'list' objects>
pop:<method 'pop' of 'list' objects>
remove:<method 'remove' of 'list' objects>
index:<method 'index' of 'list' objects>
count:<method 'count' of 'list' objects>
reverse:<method 'reverse' of 'list' objects>
sort:<method 'sort' of 'list' objects>
__class_getitem__:<method '__class_getitem__' of 'list' objects>
__doc__:Built-in mutable sequence.

8 字典dict 结构:

__repr__:<slot wrapper '__repr__' of 'dict' objects>
__hash__:None
__getattribute__:<slot wrapper '__getattribute__' of 'dict' objects>
__lt__:<slot wrapper '__lt__' of 'dict' objects>
__le__:<slot wrapper '__le__' of 'dict' objects>
__eq__:<slot wrapper '__eq__' of 'dict' objects>
__ne__:<slot wrapper '__ne__' of 'dict' objects>
__gt__:<slot wrapper '__gt__' of 'dict' objects>
__ge__:<slot wrapper '__ge__' of 'dict' objects>
__iter__:<slot wrapper '__iter__' of 'dict' objects>
__init__:<slot wrapper '__init__' of 'dict' objects>
__or__:<slot wrapper '__or__' of 'dict' objects>
__ror__:<slot wrapper '__ror__' of 'dict' objects>
__ior__:<slot wrapper '__ior__' of 'dict' objects>
__len__:<slot wrapper '__len__' of 'dict' objects>
__getitem__:<method '__getitem__' of 'dict' objects>
__setitem__:<slot wrapper '__setitem__' of 'dict' objects>
__delitem__:<slot wrapper '__delitem__' of 'dict' objects>
__contains__:<method '__contains__' of 'dict' objects>
__new__:<built-in method __new__ of type object at 0x00007FFE87D988B0>
__sizeof__:<method '__sizeof__' of 'dict' objects>
get:<method 'get' of 'dict' objects>
setdefault:<method 'setdefault' of 'dict' objects>
pop:<method 'pop' of 'dict' objects>
popitem:<method 'popitem' of 'dict' objects>
keys:<method 'keys' of 'dict' objects>
items:<method 'items' of 'dict' objects>
values:<method 'values' of 'dict' objects>
update:<method 'update' of 'dict' objects>
fromkeys:<method 'fromkeys' of 'dict' objects>
clear:<method 'clear' of 'dict' objects>
copy:<method 'copy' of 'dict' objects>
__reversed__:<method '__reversed__' of 'dict' objects>
__class_getitem__:<method '__class_getitem__' of 'dict' objects>
__doc__:dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
    (key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
    d = {}
    for k, v in iterable:
        d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
    in the keyword argument list.  For example:  dict(one=1, two=2)

9 小结

在Python中,hash()is帮助确定对象的相等性。dir()vars()揭示对象的属性和内部表示,__slots__优化内存使用。列表和字典结构有不同的内存和性能特性,字典使用哈希表进行快速访问。

目录
相关文章
|
2天前
|
机器学习/深度学习 数据可视化 TensorFlow
使用Python实现深度学习模型:图像语义分割与对象检测
【7月更文挑战第15天】 使用Python实现深度学习模型:图像语义分割与对象检测
10 2
|
5天前
|
Python
|
9天前
|
SQL 关系型数据库 MySQL
「Python入门」python操作MySQL和SqlServer
**摘要:** 了解如何使用Python的pymysql模块与MySQL数据库交互。首先,通过`pip install pymysql`安装模块。pymysql提供与MySQL的连接功能,例如创建数据库连接、执行SQL查询。在设置好MySQL环境后,使用`pymysql.connect()`建立连接,并通过游标执行SQL(如用户登录验证)。注意防止SQL注入,使用参数化查询。增删改操作需调用`conn.commit()`来保存更改。pymssql模块类似,但导入和连接对象创建略有不同。
11 0
「Python入门」python操作MySQL和SqlServer
|
14天前
|
存储 JSON 测试技术
python中json和类对象的相互转化
针对python中类对象和json的相关转化问题, 本文介绍了4种方式,涉及了三个非常强大的python库jsonpickle、attrs和cattrs、pydantic,但是这些库的功能并未涉及太深。在工作中,遇到实际的问题时,可以根据这几种方法,灵活选取。 再回到结构化测试数据的构造,当需要对数据进行建模时,也就是赋予数据业务含义,pydantic应该是首选,目前(2024.7.1)来看,pydantic的生态非常活跃,各种基于pydantic的工具也非常多,建议尝试。
|
21天前
python+Pycharm+selenium操作浏览器(Chorme或Edge)
python+Pycharm+selenium操作浏览器(Chorme或Edge)
33 1
|
4天前
|
Python
`matplotlib`是Python中一个非常流行的绘图库,它提供了丰富的绘图接口,包括二维和三维图形的绘制。`Axes3D`是`matplotlib`中用于创建三维坐标轴的对象,而`plot_surface`则是用于在三维空间中绘制表面的函数。
`matplotlib`是Python中一个非常流行的绘图库,它提供了丰富的绘图接口,包括二维和三维图形的绘制。`Axes3D`是`matplotlib`中用于创建三维坐标轴的对象,而`plot_surface`则是用于在三维空间中绘制表面的函数。
12 0
|
14天前
|
存储 Python
语音输入,python数据类型,type()用来查看数据类型,数据类型转换,int(x)转整数,float(x)转换为浮点数,str(x),将对象转为字符串,标识符,标识符不允许使用关键字,关键字参考
语音输入,python数据类型,type()用来查看数据类型,数据类型转换,int(x)转整数,float(x)转换为浮点数,str(x),将对象转为字符串,标识符,标识符不允许使用关键字,关键字参考
|
14天前
|
API Python
Python学习日记(二:函数和逻辑操作)
Python中的函数和逻辑操作至关重要。函数包括可变和不可变参数。
|
17天前
|
SQL 分布式计算 DataWorks
DataWorks产品使用合集之对于Hologres的Python查询,该如何操作
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
17 0
|
19天前
|
SQL Java 数据库连接
使用Python通过JDBC操作数据库(达梦数据库)
使用Python通过JDBC操作数据库(达梦数据库)
47 0