文章目录
python基础-内置函数3
类与对象
getattr()
getattr(object, name)
getattr(object, name, default)
object
中指定名称的属性的值。name
必须是字符串。 如果该字符串是对象的某一属性的名称,则结果将为该属性的值。 例如,getattr(x, 'foobar')
等同于 x.foobar
。 如果指定名称的属性不存在,则如果提供了 default
则返回该值,否则将引发 AttributeError
。 name
不必是一个 Python
标识符 (参见 setattr()
)。
需要注意的是getattr()
不仅可以获得属性也可以获得方法并动态调用。
# 获取属性
>>> class MyClass:
... def __init__(self):
... self.value = 42
>>> my_object = MyClass()
>>> getattr(my_object, "value")
42
>>> getattr(my_object, "key", 0)
0
>>> getattr(my_object, "key")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'key'
# 动态获取方法,并调用
>>> class MyClass:
... def __init__(self):
... self.value = 42
... def my_method(self):
... return 'Hello, World!'
>>> my_object = MyClass()
>>> getattr(my_object, 'my_method')
<bound method MyClass.my_method of <__main__.MyClass object at 0x000001DDF77AADA0>>
>>> getattr(my_object, 'my_method')()
'Hello, World!'
hasattr()
该实参是一个对象和一个字符串。如果字符串是对象的属性之一的名称,则返回 True
,否则返回 False
。(此功能是通过调用 getattr(object, name)
看是否有 AttributeError
异常来实现的。)
>>> class MyClass:
... def __init__(self):
... self.value = 42
... def my_method(self):
... return 'Hello, World!'
>>> hasattr(my_object, "value")
True
>>> hasattr(my_object, "key")
False
>>> hasattr(my_object, "my_method")
True
>>> hasattr(my_object, "__init__")
True
setattr()
setattr(object, name, value)
本函数与 getattr()
相对应。其参数为一个对象、一个字符串和一个任意值。字符串可以为某现有属性的名称,或为新属性。只要对象允许,函数会将值赋给属性。如 setattr(x, 'foobar', 123)
等价于 x.foobar = 123
。
name
无需为在 标识符和关键字 中定义的 Python
标识符除非对象选择强制这样做,例如在一个自定义的 __getattribute__()
中或是通过 __slots__
。 一个名称不为标识符的属性将不可使用点号标记来访问,但是可以通过 getattr()
等来访问
setattr()
会调用obj
的__setattr__()
# 自定义__setattr__过程,可以用来过滤非法赋值
>>> class MyClass:
... def __init__(self, value):
... self.value = value # Avoid infinite recursion
... def __setattr__(self, name, value):
self.__dict__[name] = value... if name == 'value' and not isinstance(value, int):
... raise ValueError("Value must be an integer")
... self.__dict__[name] = value
...
>>> obj = MyClass(10)
>>> obj.value
10
>>> obj.value = "10"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in __setattr__
ValueError: Value must be an integer
>>> setattr(obj,"value", "10")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in __setattr__
ValueError: Value must be an integer
# 设置未定义的属性
>>> setattr(obj, "key", 10)
>>> obj.key
10
delattr()
delattr(object, name)
这是 setattr()
的相关函数。 其参数是一个对象和一个字符串。 其中字符串必须是对象的某个属性的名称。 该函数会删除指定的属性,如果对象允许这样做的话。 例如,delattr(x, 'foobar')
等价于 del x.foobar
。
>>> class MyClass:
... def __init__(self, value):
... self.value = value
>>> delattr(obj,"value")
>>> obj.value
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'value'
# 删除没有的属性就会报错
>>> delattr(obj, 'value')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __delattr__
AttributeError: 'MyClass' object has no attribute 'value'
#自定义删除过程
>>> class MyClass:
... def __init__(self, value):
... self.value = value
... def __delattr__(self, name):
... # 自定义属性删除行为
... print(f"删除 {name}")
... super().__delattr__(name)
...
>>> obj = MyClass(1)
>>> delattr(obj, "value")
删除 value
vars()
vars(object)
返回模块、类、实例或任何其它具有 __dict__
属性的对象的__dict__
属性。
模块和实例这样的对象具有可更新的 __dict__
属性;但是,其它对象的 __dict__
属性可能会设为限制写入(例如,类会使用 types.MappingProxyType
来防止直接更新字典)。
不带参数时,vars()
的行为类似 locals()
。 请注意,locals
字典仅对于读取起作用,因为对 locals 字典的更新会被忽略。
如果指定了一个对象但它没有 __dict__
属性(例如,当它所属的类定义了__slots__
属性时)则会引发 TypeError
异常。
>>> class MyClass:
... def __init__(self, value):
... self.value = value
# 对象
>>> obj = MyClass(10)
>>> vars(obj)
{'value': 10}
# 类
>>> vars(MyClass)
mappingproxy({'__module__': '__main__', '__init__': <function MyClass.__init__ at 0x7f38c5631c60>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None})
# 执行环境变量
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'asyncio': <module 'asyncio' from '/home/xxxxx/lib/python3.11/asyncio/__init__.py'>, 'async_generator': <function async_generator at 0x7f38c5f177e0>, 'main': <function main at 0x7f38c5610fe0>, 'async_gen': <function async_gen at 0x7f38c5fe49a0>, 'MyCustomClass': <class '__main__.MyCustomClass'>, 'my_object': <__main__.MyClass object at 0x7f38c5617810>, 'MyClass': <class '__main__.MyClass'>, 'obj': <__main__.MyClass object at 0x7f38c5638710>}
dir()
dir()
dir(object)
如果没有实参,则返回当前本地作用域中的名称列表。如果有实参,它会尝试返回该对象的有效属性列表。
如果对象有一个名为 __dir__()
的方法,则该方法将被调用并且必须返回由属列组成的列表。 这允许实现自定义This allows objects that implement a custom __getattr__()
或 __getattribute__()
函数的对象能够定制 dir()
报告其属性的方式。
如果对象未提供 __dir__()
,该函数会尽量从对象所定义的__dict__
属性和其类型对象中收集信息。 结果列表不一定是完整的,并且当对象具有自定义的 __getattr__()
时还可能是不准确的。
默认的 dir()
机制对不同类型的对象行为不同,它会试图返回最相关而不是最全的信息:
- 如果对象是模块对象,则列表包含模块的属性名称。
- 如果对象是类型或类对象,则列表包含它们的属性名称,并且递归查找所有基类的属性。
- 否则,列表包含对象的属性名称,它的类属性名称,并且递归查找它的类的所有基类的属性
# 对象
>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'value']
# 类
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
# 本地域
>>> dir()
['MyClass', 'MyCustomClass', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'async_gen', 'async_generator', 'asyncio', 'main', 'my_object', 'obj']
# 模块
>>> import os
>>> dir(os)
['CLD_CONTINUED', 'CLD_DUMPED', 'CLD_EXITED', 'CLD_KILLED', 'CLD_STOPPED', 'CLD_TRAPPED', 'DirEntry', 'EFD_CLOEXEC', 'EFD_NONBLOCK', 'EFD_SEMAPHORE', 'EX_CANTCREAT', 'EX_CONFIG', 'EX_DATAERR', 'EX_IOERR', 'EX_NOHOST', 'EX_NOINPUT', 'EX_NOPERM', 'EX_NOUSER', 'EX_OK', 'EX_OSERR', 'EX_OSFILE', 'EX_PROTOCOL', 'EX_SOFTWARE', 'EX_TEMPFAIL', 'EX_UNAVAILABLE', 'EX_USAGE', 'F_LOCK', 'F_OK', 'F_TEST', 'F_TLOCK', 'F_ULOCK', 'GRND_NONBLOCK', 'GRND_RANDOM', 'GenericAlias', 'Mapping', 'MutableMapping', 'NGROUPS_MAX', 'O_ACCMODE', 'O_APPEND', 'O_ASYNC', 'O_CLOEXEC', 'O_CREAT', 'O_DIRECT', 'O_DIRECTORY', 'O_DSYNC', 'O_EXCL', 'O_FSYNC', 'O_LARGEFILE', 'O_NDELAY', 'O_NOATIME', 'O_NOCTTY', 'O_NOFOLLOW', 'O_NONBLOCK', 'O_PATH', 'O_RDONLY', 'O_RDWR', 'O_RSYNC', 'O_SYNC', 'O_TMPFILE', 'O_TRUNC', 'O_WRONLY', 'POSIX_FADV_DONTNEED', 'POSIX_FADV_NOREUSE', 'POSIX_FADV_NORMAL', 'POSIX_FADV_RANDOM', 'POSIX_FADV_SEQUENTIAL', 'POSIX_FADV_WILLNEED', 'POSIX_SPAWN_CLOSE', 'POSIX_SPAWN_DUP2', 'POSIX_SPAWN_OPEN', 'PRIO_PGRP', 'PRIO_PROCESS', 'PRIO_USER', 'P_ALL', 'P_NOWAIT', 'P_NOWAITO', 'P_PGID', 'P_PID', 'P_WAIT', 'PathLike', 'RTLD_DEEPBIND', 'RTLD_GLOBAL', 'RTLD_LAZY', 'RTLD_LOCAL', 'RTLD_NODELETE', 'RTLD_NOLOAD', 'RTLD_NOW', 'R_OK', 'SCHED_BATCH', 'SCHED_FIFO', 'SCHED_IDLE', 'SCHED_OTHER', 'SCHED_RESET_ON_FORK', 'SCHED_RR', 'SEEK_CUR', 'SEEK_DATA', 'SEEK_END', 'SEEK_HOLE', 'SEEK_SET', 'SPLICE_F_MORE', 'SPLICE_F_MOVE', 'SPLICE_F_NONBLOCK', 'ST_APPEND', 'ST_MANDLOCK', 'ST_NOATIME', 'ST_NODEV', 'ST_NODIRATIME', 'ST_NOEXEC', 'ST_NOSUID', 'ST_RDONLY', 'ST_RELATIME', 'ST_SYNCHRONOUS', 'ST_WRITE', 'TMP_MAX', 'WCONTINUED', 'WCOREDUMP', 'WEXITED', 'WEXITSTATUS', 'WIFCONTINUED', 'WIFEXITED', 'WIFSIGNALED', 'WIFSTOPPED', 'WNOHANG', 'WNOWAIT', 'WSTOPPED', 'WSTOPSIG', 'WTERMSIG', 'WUNTRACED', 'W_OK', 'XATTR_CREATE', 'XATTR_REPLACE', 'XATTR_SIZE_MAX', 'X_OK', '_Environ', '__all__', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_check_methods', '_execvpe', '_exists', '_exit', '_fspath', '_fwalk', '_get_exports_list', '_spawnvef', '_walk', '_wrap_close', 'abc', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'chown', 'chroot', 'close', 'closerange', 'confstr', 'confstr_names', 'cpu_count', 'ctermid', 'curdir', 'defpath', 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'environb', 'error', 'eventfd', 'eventfd_read', 'eventfd_write', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fchdir', 'fchmod', 'fchown', 'fdatasync', 'fdopen', 'fork', 'forkpty', 'fpathconf', 'fsdecode', 'fsencode', 'fspath', 'fstat', 'fstatvfs', 'fsync', 'ftruncate', 'fwalk', 'get_blocking', 'get_exec_path', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getegid', 'getenv', 'getenvb', 'geteuid', 'getgid', 'getgrouplist', 'getgroups', 'getloadavg', 'getlogin', 'getpgid', 'getpgrp', 'getpid', 'getppid', 'getpriority', 'getrandom', 'getresgid', 'getresuid', 'getsid', 'getuid', 'getxattr', 'initgroups', 'isatty', 'kill', 'killpg', 'lchown', 'linesep', 'link', 'listdir', 'listxattr', 'lockf', 'login_tty', 'lseek', 'lstat', 'major', 'makedev', 'makedirs', 'minor', 'mkdir', 'mkfifo', 'mknod', 'name', 'nice', 'open', 'openpty', 'pardir', 'path', 'pathconf', 'pathconf_names', 'pathsep', 'pipe', 'pipe2', 'popen', 'posix_fadvise', 'posix_fallocate', 'posix_spawn', 'posix_spawnp', 'pread', 'preadv', 'putenv', 'pwrite', 'pwritev', 'read', 'readlink', 'readv', 'register_at_fork', 'remove', 'removedirs', 'removexattr', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sched_get_priority_max', 'sched_get_priority_min', 'sched_getaffinity', 'sched_getparam', 'sched_getscheduler', 'sched_param', 'sched_rr_get_interval', 'sched_setaffinity', 'sched_setparam', 'sched_setscheduler', 'sched_yield', 'sendfile', 'sep', 'set_blocking', 'set_inheritable', 'setegid', 'seteuid', 'setgid', 'setgroups', 'setpgid', 'setpgrp', 'setpriority', 'setregid', 'setresgid', 'setresuid', 'setreuid', 'setsid', 'setuid', 'setxattr', 'spawnl', 'spawnle', 'spawnlp', 'spawnlpe', 'spawnv', 'spawnve', 'spawnvp', 'spawnvpe', 'splice', 'st', 'stat', 'stat_result', 'statvfs', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sync', 'sys', 'sysconf', 'sysconf_names', 'system', 'tcgetpgrp', 'tcsetpgrp', 'terminal_size', 'times', 'times_result', 'truncate', 'ttyname', 'umask', 'uname', 'uname_result', 'unlink', 'unsetenv', 'urandom', 'utime', 'wait', 'wait3', 'wait4', 'waitid', 'waitid_result', 'waitpid', 'waitstatus_to_exitcode', 'walk', 'write', 'writev']
property()
class property(fget=None, fset=None, fdel=None, doc=None)
返回 property 属性。
fget 是获取属性值的函数。 fset 是用于设置属性值的函数。 fdel 是用于删除属性值的函数。并且 doc 为属性对象创建文档字符串。
>>> class C:
... def __init__(self):
... self._x = None
... def getx(self):
... return self._x
... def setx(self, value):
... self._x = value
... def delx(self):
... del self._x
... x = property(getx, setx, delx, "I'm the 'x' property.")
...
>>> c = c()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'c' is not defined. Did you mean: 'C'?
>>> c = C()
>>> c.x = 10
>>> c._x
10
class Parrot:
def __init__(self):
self._voltage = 100000
@property
def voltage(self):
"""Get the current voltage."""
return self._voltage
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
super()
class super
class super(type, object_or_type=None)
返回一个代理对象,它会将方法调用委托给 type
的父类或兄弟类。 这对于访问已在类中被重写的继承方法很有用。
object_or_type
确定要用于搜索的 method resolution order
。 搜索会从 type
之后的类开始。
举例来说,如果 object_or_type
的 __mro__
为 D -> B -> C -> A -> object
并且 type
的值为 B
,则 super()
将会搜索 C -> A -> object
。
object_or_type
的 __mro__
属性列出了 getattr()
和 super()
所共同使用的方法解析搜索顺序。 该属性是动态的并可在任何继承层级结构发生更新时被改变。
如果省略第二个参数,则返回的超类对象是未绑定的。 如果第二个参数为一个对象,则 isinstance(obj, type)
必须为真值。 如果第二个参数为一个类型,则 issubclass(type2, type)
必须为真值(这适用于类方法)。
super
有两个典型用例。 在具有单继承的类层级结构中,super
可用来引用父类而不必显式地指定它们的名称,从而令代码更易维护。 这种用法与其他编程语言中 super
的用法非常相似。
第二个用例是在动态执行环境中支持协作多重继承。 此用例为 Python
所独有而不存在于静态编码语言或仅支持单继承的语言当中。 这使用实现“菱形图”成为可能,即有多个基类实现相同的方法。 好的设计强制要求这样的方法在每个情况下都具有相同的调用签名(因为调用顺序是在运行时确定的,也因为这个顺序要适应类层级结构的更改,还因为这个顺序可能包括在运行时之前未知的兄弟类)。
对于以上两个用例,典型的超类调用看起来是这样的:
class C(B):
def method(self, arg):
super().method(arg)
除了方法查找之外,super()
也可用于属性查找。 一个可能的应用场合是在上级或同级类中调用 描述器。
请注意 super()
被实现为为显式的带点号属性查找的绑定过程的组成部分,例如 super().__getitem__(name)
。 它做到这一点是通过实现自己的 __getattribute__()
方法以便能够按支持协作多重继承的可预测的顺序来搜索类。 相应地,super()
在像 super()[name]
这样使用语句或运算符进行隐式查找时则是未定义的。
还要注意的是,除了零个参数的形式以外,super()
并不限于在方法内部使用。 两个参数的形式明确指定参数并进行相应的引用。 零个参数的形式仅适用于类定义内部,因为编译器需要填入必要的细节以正确地检索到被定义的类,还需要让普通方法访问当前实例。
classmethod()
@classmethod
把一个方法封装成类方法。
类方法隐含的第一个参数就是类,就像实例方法接收实例作为参数一样。要声明一个类方法,按惯例请使用以下方案:
class C:
@classmethod
def f(cls, arg1, arg2): ...
类方法的调用可以在类上进行 (例如 C.f()
) 也可以在实例上进行 (例如 C().f()
)。 其所属类以外的类实例会被忽略。 如果类方法在其所属类的派生类上调用,则该派生类对象会被作为隐含的第一个参数被传入。
在 3.9 版本发生变更: 类方法现在可以包装其他 描述器 例如
property()
。
在 3.10 版本发生变更: 类方法现在继承了方法的属性(__module__、 __name__、 __qualname__、 __doc__ 和 __annotations__
),并拥有一个新的__wrapped__
属性。
在 3.11 版本发生变更: 类方法不再可以包装其他descriptors
例如property()
。
staticmethod()
@staticmethod
将方法转换为静态方法。
静态方法不会接收隐式的第一个参数。要声明一个静态方法,请使用此语法
class C:
@staticmethod
def f(arg1, arg2, argN): ...
静态方式既可以在类上调用 (如 C.f()
),也可以在实例上调用 (如 C().f()
)。 此外,静态方法 descriptor
也属于可调用对象,因而它们可以在类定义中使用 (如 f()
)。
像所有装饰器一样,也可以像常规函数一样调用 staticmethod
,并对其结果执行某些操作。比如某些情况下需要从类主体引用函数并且您希望避免自动转换为实例方法。对于这些情况,请使用此语法:
def regular_function():
...
class C:
method = staticmethod(regular_function)
在 3.10 版本发生变更: 静态方法继承了方法的多个属性(
__module__、 __name__、 __qualname__、 __doc__
和__annotations__
),还拥有一个新的__wrapped__
属性,并且现在还可以作为普通函数进行调用。
isinstance()
isinstance(object, classinfo)
如果 object
参数是 classinfo
参数的实例,或者是其 (直接、间接或 虚拟) 子类的实例则返回 True
。 如果 object
不是给定类型的对象,则该函数总是返回 False
。 如果 classinfo
是由类型对象结成的元组 (或是由其他此类元组递归生成) 或者是多个类型的 union
类型,则如果 object
是其中任一类型的实例时将会返回 True
。 如果 classinfo
不是一个类型或类型元组及此类元组,则会引发 TypeError
异常。 如果之前的检查成功执行则可以不会为无效的类型引发 TypeError
。
在 3.10 版本发生变更: classinfo 可以是一个 union 类型。
>>> s = ""
>>> isinstance(s,str)
True
>>> isinstance(s,object)
True
issubclass()
issubclass(class, classinfo)
如果 class
是 classinfo
的子类(直接、间接或 虚的 ),则返回 True
。类将视为自己的子类。classinfo
可为类对象的元组(或递归地,其他这样的元组)或 union
类型,这时如果 class
是 classinfo
中任何条目的子类,则返回 True
。任何其他情况都会触发 TypeError
异常。
在 3.10 版本发生变更:
classinfo
可以是一个union
类型。
>>> issubclass(str, object)
True
callable()
callable(object)
如果 object
参数是可调用的则返回 True
,否则返回 False
。 如果返回 True
,调用仍可能失败,但如果返回 False
,则调用 object
肯定不会成功。 请注意类是可调用的(调用类将返回一个新的实例);如果实例所属的类有 __call__()
方法则它就是可调用的。
Added in version 3.2: 这个函数一开始在 Python 3.0 被移除了,但在 Python 3.2 被重新加入。
>>> func = lambda x: x**2
>>> type(func)
<class 'function'>
>>> callable(func)
True
>>> class C:
... def __init__(self,x):
... self._x = x
... def __call__(self, b):
... return self._x+b
...
>>> c = C(10)
>>> callable(c)
True
>>> c(10)
20
object()
class object
返回一个不带特征的新对象。object
是所有类的基类。它带有所有 Python
类实例均通用的方法。本函数不接受任何参数。
由于 object
没有 __dict__
,因此无法将任意属性赋给 object
的实例。
repr()
repr(object)
返回包含一个对象的可打印表示形式的字符串。 对于许多类型而言,此函数会尝试返回一个具有与传给 eval()
时相同的值的字符串;在其他情况下,其表示形式将为一个包含对象类型名称和通常包括对象名称和地址的额外信息的用尖括号括起来的字符串。 一个类可以通过定义__repr__()
方法来控制此函数为其实例所返回的内容。 如果 sys.displayhook()
不可访问,则此函数将会引发 RuntimeError
。
该类具有自定义的表示形式,它可被求值为:
>>> class Person:
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __repr__(self):
... return f"Person('{self.name}', {self.age})"
...
>>> Person("Alice", 20)
Person('Alice', 20)
>>> repr( Person("Alice", 20))
"Person('Alice', 20)"
>>> repr(Person("张三", 20))
"Person('张三', 20)"
ascii()
ascii(object)
与 repr()
类似,返回一个包含对象的可打印表示形式的字符串,但是使用 \x、\u
和 \U
对 repr()
返回的字符串中非 ASCII
编码的字符进行转义。生成的字符串和 Python 2
的 repr()
返回的结果相似。
>>> ascii(Person("Alice", 20))
"Person('Alice', 20)"
>>> ascii(Person("张三", 20))
"Person('\\u5f20\\u4e09', 20)"
id()
id(object)
返回对象的“标识值”。该值是一个整数,在此对象的生命周期中保证是唯一且恒定的。两个生命期不重叠的对象可能具有相同的 id()
值。
CPython
实现细节: 这是对象在内存中的地址。
>>> id("")
8906752
hash()
hash(object)
返回该对象的哈希值(如果它有的话)。哈希值是整数。它们在字典查找元素时用来快速比较字典的键。相同大小的数字变量有相同的哈希值(即使它们类型不同,如 1
和 1.0
)。
对于具有自定义 __hash__()
方法的对象,请注意 hash()
会根据宿主机的字长来截断返回值。
在 Python 中,可哈希(hashable)的类型是指那些在其生命周期内是不可变的,并且可以通过 hash()
函数计算出哈希值的类型。以下是一些常见的可哈希类型:
- 不可变的基本数据类型:
- 整数(
int
) - 浮点数(
float
) - 复数(
complex
) - 字符串(
str
) - 元组(
tuple
)
- 整数(
- 不可变集合类型:
- 冻结集合(
frozenset
)
- 冻结集合(
- 自定义的不可变类型:
- 如果你定义的类使用了不可变的数据作为属性,并且实现了
__hash__()
方法以及__eq__()
方法,那么这个类的实例也是可哈希的。
- 如果你定义的类使用了不可变的数据作为属性,并且实现了
- 原子类型:
- 原子类型是指不可分割的、不可变的数据类型,如原子类型的数组或字节序列。Python 中的
bytes
和bytearray
就是原子类型。
值得注意的是,可变类型(例如列表list
、字典dict
、集合set
)是不可哈希的,因为它们在其生命周期内是可变的,并且不具有固定的哈希值。如果你尝试对一个不可哈希的对象调用hash()
函数,会引发TypeError
。
- 原子类型是指不可分割的、不可变的数据类型,如原子类型的数组或字节序列。Python 中的
>>> a = "Hello"
>>> hash(s)
0
>>> hash("Hello")
-3718921152812087750
>>> hash([1,2,3,4])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash(10)
10
type()
class type(object)
class type(name, bases, dict, **kwds)
传入一个参数时,返回 object
的类型。 返回值是一个 type
对象,通常与 object.__class__
所返回的对象相同。
推荐使用 isinstance()
内置函数来检测对象的类型,因为它会考虑子类的情况。
传入三个参数时,返回一个新的 type
对象。 这在本质上是 class
语句的一种动态形式,name
字符串即类名并会成为 __name__
属性;base
s 元组包含基类并会成为 __bases__
属性;如果为空则会添加所有类的终极基类 object
。 dict
字典包含类主体的属性和方法定义;它在成为 dict 属性之前可能会被拷贝或包装。 下面两条语句会创建相同的 type
对象:
>>> class X:
... a = 1
...
>>> X = type('X', (), dict(a=1))
>>> X
<class '__main__.X'>
>>> X()
<__main__.X object at 0x7f874f1f8210>
>>> type("")
<class 'str'>
>>> type(type(str))
<class 'type'>
>>> type(str) == "<class 'str'>"
False