关于python:如何在python3中替换has_key?

How to replace has_key in python3?

我尝试安装自动自我控制,但在执行此命令时卡住了:

1
sudo /usr/bin/python auto-selfcontrol.py

显示错误:

AttributeError: 'dict' object has no attribute 'has_key'

我正在寻找解决方案,结果替换了in operator中的has_键,但正如我只知道Python的基础知识一样,代码对我来说相当复杂。

有三个地方使用过钥匙,你能帮我换一下吗?这样我就可以和Python一起跑了。

1。

1
2
3
4
def check_if_running(username):
""" checks if self-control is already running."""
defaults = get_selfcontrol_settings(username)
return defaults.has_key("BlockStartedDate") and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

2-4。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def check_config(config):
""" checks whether the config file is correct"""
if not config.has_key("username"):
    exit_with_error("No username specified in config.")
if config["username"] not in get_osx_usernames():
    exit_with_error(
           "Username '{username}' unknown.
Please use your OSX username instead.
"
\
           "If you have trouble finding it, just enter the command 'whoami'
"
\
           "in your terminal.".format(
                    username=config["username"]))
if not config.has_key("selfcontrol-path"):
    exit_with_error("The setting 'selfcontrol-path' is required and must point to the location of SelfControl.")
if not os.path.exists(config["selfcontrol-path"]):
    exit_with_error(
           "The setting 'selfcontrol-path' does not point to the correct location of SelfControl." \
           "Please make sure to use an absolute path and include the '.app' extension," \
           "e.g. /Applications/SelfControl.app")
if not config.has_key("block-schedules"):
    exit_with_error("The setting 'block-schedules' is required.")
if len(config["block-schedules"]) == 0:
    exit_with_error("You need at least one schedule in 'block-schedules'.")
if config.get("host-blacklist", None) is None:
    print("WARNING:")
    msg ="It is not recommended to directly use SelfControl's blacklist. Please use the 'host-blacklist'" \
         "setting instead."
    print(msg)
    syslog.syslog(syslog.LOG_WARNING, msg)


虽然其他答案中的零碎解决方案会起作用,但这种方法存在缺陷,因为它太容易犯一个小错误、错过需要修复的地方等。更好的解决方案是只使用2to3转换器。您可以一次性修复所有文件:

1
$ 2to3 -f has_key -w auto-selfcontrol.py

只运行has_key固定器,它从dict.has_key(key)转换为key in dict。当然可以自己修复,但这是一个简单的编程修复程序可以正常工作的例子。您可能只想在不使用-f has_key的情况下运行它,因此它会立即应用所有修复程序,以防PY2和PY3之间存在任何其他破坏性更改。

除了py2 str类型的改变(在py3中给定的str字是否应该是bytesstr的代码逻辑决定)和整数除法(在/可能需要改变)外,2to3几乎可以自动处理所有的事情。到//,根据计算是逻辑上的浮点划分还是楼层划分)。但对于has_key来说,这是相当可靠的。


在python3.7中测试。

1
2
   tmp = {'a':1, 'b':2, 'c':3}
   print(tmp.__contains__('a')) #True


解决方案的正式来源如下:https://portingguide.readthedocs.io/en/latest/dicts.html

TL;DR是:

1
some_dict.has_key('some key')

现在是:

1
'some key' in some_dict

因此,在您的代码中:

1
return defaults.has_key("BlockStartedDate") and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

变成:

1
return"BlockStartedDate" in defaults and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

类似地,行如下:

1
2
if not config.has_key("selfcontrol-path"):
    # do something

变得像:

1
2
if"selfcontrol-path" not in config:
    # do something

请注意,您也可以编写if not"selfcontrol-path" in config:,但上面给出的示例被认为是更为Python式的,应该首选。


更换如下

1。

1
2
3
4
def check_if_running(username):
""" checks if self-control is already running."""
defaults = get_selfcontrol_settings(username)
return"BlockStartedDate" in defaults and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

2-4。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def check_config(config):
""" checks whether the config file is correct"""
if not"username" in config:
    exit_with_error("No username specified in config.")
if config["username"] not in get_osx_usernames():
    exit_with_error(
           "Username '{username}' unknown.
Please use your OSX username instead.
"
\
           "If you have trouble finding it, just enter the command 'whoami'
"
\
           "in your terminal.".format(
                    username=config["username"]))
if not"selfcontrol-path" in config:
    exit_with_error("The setting 'selfcontrol-path' is required and must point to the location of SelfControl.")
if not os.path.exists(config["selfcontrol-path"]):
    exit_with_error(
           "The setting 'selfcontrol-path' does not point to the correct location of SelfControl." \
           "Please make sure to use an absolute path and include the '.app' extension," \
           "e.g. /Applications/SelfControl.app")
if not"block-schedules" in config:
    exit_with_error("The setting 'block-schedules' is required.")
if len(config["block-schedules"]) == 0:
    exit_with_error("You need at least one schedule in 'block-schedules'.")
if config.get("host-blacklist", None) is None:
    print("WARNING:")
    msg ="It is not recommended to directly use SelfControl's blacklist. Please use the 'host-blacklist'" \
         "setting instead."
    print(msg)
    syslog.syslog(syslog.LOG_WARNING, msg)