Python内置bool方法__ror__的目的是什么?

14 投票
2 回答
5602 浏览
提问于 2025-04-18 16:36

在交互式解释器中,如果你按顺序输入以下内容,你会看到一些很有趣的东西:

1) help() - 这个命令会给你一些帮助信息。

2) modules - 这个命令会列出你可以使用的模块。

3) __builtin__ - 这个命令会显示一些内置的功能。

当我仔细查看输出时,发现了在 class bool 中的一些内容:

__or__(...)
    x.__or__(y) <==> x|y

然后稍后又看到:

__ror__(...)
    x.__ror__(y) <==> y|x

最后这个方法似乎是在描述 反向或。这个方法为什么会存在呢?有什么情况会导致 __or__(...) 返回的结果和 __ror__(...) 不一样呢?

2 个回答

2

这里有一个在REPL中实用的例子:

假设你想查看一个对象的内容。这里我用时间模块作为例子。

>>> import time
>>> vars(time)
{'timezone': 0, '_STRUCT_TM_ITEMS': 11, '__package__': '', 'mktime': <built-in function mktime>, 'altzone': 0, '__doc__': 'This module provides various functions to manipulate time values.\n\nThere are two standard representations of time.  One is the number\nof seconds since the Epoch, in UTC (a.k.a. GMT).  It may be an integer\nor a floating point number (to represent fractions of seconds).\nThe Epoch is system-defined; on Unix, it is generally January 1st, 1970.\nThe actual value can be retrieved by calling gmtime(0).\n\nThe other representation is a tuple of 9 integers giving local time.\nThe tuple items are:\n  year (including century, e.g. 1998)\n  month (1-12)\n  day (1-31)\n  hours (0-23)\n  minutes (0-59)\n  seconds (0-59)\n  weekday (0-6, Monday is 0)\n  Julian day (day in the year, 1-366)\n  DST (Daylight Savings Time) flag (-1, 0 or 1)\nIf the DST flag is 0, the time is given in the regular time zone;\nif it is 1, the time is given in the DST time zone;\nif it is -1, mktime() should guess based on the date and time.\n\nVariables:\n\ntimezone -- difference in seconds between UTC and local standard time\naltzone -- difference in  seconds between UTC and local DST time\ndaylight -- whether local time should reflect DST\ntzname -- tuple of (standard time zone name, DST time zone name)\n\nFunctions:\n\ntime() -- return current time in seconds since the Epoch as a float\nclock() -- return CPU time since process start as a float\nsleep() -- delay for a number of seconds given as a float\ngmtime() -- convert seconds since Epoch to UTC tuple\nlocaltime() -- convert seconds since Epoch to local time tuple\nasctime() -- convert time tuple to string\nctime() -- convert time in seconds to string\nmktime() -- convert local time tuple to seconds since Epoch\nstrftime() -- convert time tuple to string according to format specification\nstrptime() -- parse string to time tuple according to format specification\ntzset() -- change the local timezone', 'strptime': <built-in function strptime>, 'clock_settime': <built-in function clock_settime>, 'CLOCK_MONOTONIC': 1, 'strftime': <built-in function strftime>, 'time': <built-in function time>, 'CLOCK_PROCESS_CPUTIME_ID': 2, 'monotonic': <built-in function monotonic>, 'gmtime': <built-in function gmtime>, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'get_clock_info': <built-in function get_clock_info>, 'clock_getres': <built-in function clock_getres>, 'asctime': <built-in function asctime>, 'CLOCK_THREAD_CPUTIME_ID': 3, 'tzname': ('UTC', 'UTC'), 'CLOCK_MONOTONIC_RAW': 4, 'clock_gettime': <built-in function clock_gettime>, 'clock': <built-in function clock>, 'ctime': <built-in function ctime>, '__spec__': ModuleSpec(name='time', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), 'sleep': <built-in function sleep>, 'localtime': <built-in function localtime>, 'struct_time': <class 'time.struct_time'>, 'CLOCK_REALTIME': 0, 'perf_counter': <built-in function perf_counter>, 'tzset': <built-in function tzset>, 'process_time': <built-in function process_time>, 'daylight': 0, '__name__': 'time'}

你可以使用pprint来让内容更容易阅读。

>>> import pprint
>>> pprint(vars(time))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'module' object is not callable
>>> pprint.pprint(vars(time))
{'CLOCK_MONOTONIC': 1,
 'CLOCK_MONOTONIC_RAW': 4,
 'CLOCK_PROCESS_CPUTIME_ID': 2,
 'CLOCK_REALTIME': 0,
 'CLOCK_THREAD_CPUTIME_ID': 3,
 '_STRUCT_TM_ITEMS': 11,
 '__doc__': 'This module provides various functions to manipulate time '
            'values.\n'
            '\n'
            'There are two standard representations of time.  One is the '
            'number\n'
            'of seconds since the Epoch, in UTC (a.k.a. GMT).  It may be an '
            'integer\n'
            'or a floating point number (to represent fractions of seconds).\n'
            'The Epoch is system-defined; on Unix, it is generally January '
            '1st, 1970.\n'
            'The actual value can be retrieved by calling gmtime(0).\n'
...

但是如果我需要这样做很多次,反复输入pprint和括号就会很麻烦,所以我决定定义一个特殊的对象:

>>> pp = type("", (), {"__ror__": lambda self, v: pprint.pprint(v)})()
>>> vars(time) | pp
{'CLOCK_MONOTONIC': 1,
 'CLOCK_MONOTONIC_RAW': 4,
 'CLOCK_PROCESS_CPUTIME_ID': 2,
 'CLOCK_REALTIME': 0,
 'CLOCK_THREAD_CPUTIME_ID': 3,
 '_STRUCT_TM_ITEMS': 11,
 '__doc__': 'This module provides various functions to manipulate time '
            'values.\n'
            '\n'
            'There are two standard representations of time.  One is the '
            'number\n'
            'of seconds since the Epoch, in UTC (a.k.a. GMT).  It may be an '
            'integer\n'
            'or a floating point number (to represent fractions of seconds).\n'
            'The Epoch is system-defined; on Unix, it is generally January '
            '1st, 1970.\n'
            'The actual value can be retrieved by calling gmtime(0).\n'
...

现在我只需在想要美化输出的时候加上"| pp"就可以了。

27

假设你自己写了一个整数类,并且希望它能和Python内置的整数一起使用。你可能会定义一个叫做 __or__ 的方法。

class MyInt(int):

    def __or__(self, other):
        # Not a recommended implementation!
        return self | int(other)

这样你就可以写出类似下面的代码:

# Because this is equivalent to MyInt.__or__(MyInt(6), 7)
MyInt(6) | 7

但是,Python不知道该如何处理下面的情况:

# First interpretation is int.__or__(7, MyInt(6))
7 | MyInt(6)

因为 int.__or__ 不知道如何和你的 MyInt 实例一起工作。在这种情况下,Python会调换操作数的顺序,然后尝试:

MyInt.__ror__(MyInt(6), 7)

也就是说,它会在右边那个参数的类里寻找调换顺序后的魔法方法。

撰写回答