I am a fairly new developer in Python and was getting accustomed to the idea of "Duck Typing".
我是一个相当新手的开发人员,我已经习惯了“鸭子打字”的想法。
I have a class I used in another module to do particular things with it, for example, access it's name and version. This module obviously cannot handle arbitrary values and needs the name to be a string and version to be an integer.
我在另一个模块中使用了一个类来对它执行特定的操作,例如,访问它的名称和版本。该模块显然不能处理任意值,需要名称为字符串,版本为整数。
Currently, I am enforcing the type of input to my class properties using isinstance():
目前,我正在使用isInstance()将输入类型强制输入到我的类属性:
class ExampleObject(object):
def __init__(self):
self._name = None
self._version = None
@property
def name(self):
return self._name
@name.setter
def name(self, name):
if not isinstance(name, str) and name is not None:
raise ValueError("Expected string, got {0}".format(type(name)))
self._name = name
@property
def version(self):
return self._name
@version.setter
def version(self, version_number):
if not isinstance(version_number, int) and version_number is not None:
raise ValueError("Expected int, got {0}".format(type(version_number)))
self._version = version_number
If I go with the idea of Duck typing, I should not be enforcing a particular type to my properties. If I drop my type checking and some other developer starts using these properties for other data types, it can lead to the module I wrote breaking. Basically, the module expecting an integer and it gets something else. What's the correct approach to this?
如果我采用Duck类型的想法,我不应该强制我的属性使用特定的类型。如果我放弃类型检查,而其他开发人员开始将这些属性用于其他数据类型,可能会导致我编写的模块崩溃。基本上,该模块需要一个整数,但它得到的是其他值。解决这个问题的正确方法是什么?
I checked several related questions regarding this but none of them covers what would happen if we skip the type checking and how to enforce that other developers don't break things because they were not aware of another module using these properties to perform type specific things.
我检查了几个与此相关的问题,但没有一个涉及到如果我们跳过类型检查会发生什么,以及如何强制其他开发人员不破坏东西,因为他们不知道另一个模块使用这些属性来执行特定于类型的事情。
更多回答
"Please note I can only use python 2 to try anything." - Python 2 is end of life since Jan 1st 2020. If you are trying to maintain / develop an application that is Python 2 (only) you are just digging yourself deeper into your hole. And if you can't install Python 3 side-by-side with Python 2 to try things out, there is something wrong with your platform!
“请注意,我只能使用Python2来尝试任何事情。”--从2020年1月1日起,Python2将会被淘汰。如果您正在尝试维护/开发一个(仅限)是Python2的应用程序,那么您只是在自己的洞穴中挖得更深。如果你不能同时安装Python3和Python2来试用,那就是你的平台有问题!
Hey @StephenC, I myself would like to switch to python 3 but I am not sure if my code will be compatible with other pieces of software. For context, I am working on a class which is generic enough to be used in several places or software with their own python version. The place where I need it runs python 3.7 by default which is not a problem but there are other software which can use this class running on python 2. These are third party software and I am not in control over their native python versions.
嘿@StehenC,我自己也想切换到python3,但我不确定我的代码是否能与其他软件兼容。对于上下文,我正在处理一个足够通用的类,可以在几个地方使用,或者使用他们自己的Python版本的软件。我需要它的地方默认运行的是python3.7,这不是问题,但是有其他软件可以使用这个类在python2上运行。这些是第三方软件,我不能控制他们的原生python版。
"I myself would like to switch to python 3 but I am not sure if my code will be compatible with other pieces of software." - The best (in fact only) way to find out is to try it. "... but there are other software which can use this class running on python 2." - The practical solution in the long run is to make it their problem. State that your code requires Python 3.7 or later. If "they" then want to run it on an end-of-life version of Python, that is their problem, not yours. (Unless "they" are paying you good money to do the extra work to support their legacy requirements.)
“我自己也想改用Python3,但我不确定我的代码是否能与其他软件兼容。”--最好的(事实上只有)方法就是试一试。“……但是有其他软件可以使用这个类,在python2上运行。”-从长远来看,实际的解决方案是让它成为他们的问题。声明您的代码需要使用Python3.7或更高版本。如果“他们”想要在生命终结版本的Python上运行它,那是他们的问题,不是你的问题。(除非“他们”付给你一大笔钱让你做额外的工作,以支持他们的遗留需求。)
@StephenC, very well, thanks for pointing this out. I wasn't even thinking on these terms and now that I focusing some thought on this, I wrote quite a few things in Python 2 without thinking over whether it is really necessary or not in the name of compatibility. I will switch to Python 3 and just see what happens. I will remove the Python 2 comment in my question.
@StehenC,很好,谢谢你指出这一点。我甚至没有想过这些术语,现在我把一些想法集中在这个问题上,我用Python2编写了相当多的东西,而没有考虑是否真的有必要以兼容性的名义。我将切换到Python3,看看会发生什么。我将删除我问题中的Python2注释。
优秀答案推荐
Python's duck typing puts the onus on you to enforce it. If the parameter will be passed by the user, it can be a good idea to perform casting and/or type validation. For example, you can try casting version_number
to an int using the built-in int()
method. If this fails (ie. version_number
cannot be converted to a string), the int()
method raises a ValueError for you, which you can check for as follows:
Python的鸭子类型将强制执行它的责任推给了您。如果参数将由用户传递,那么执行强制转换和/或类型验证可能是个好主意。例如,您可以尝试使用内置的int()方法将VERSION_NUMBER转换为int。如果此操作失败(即VERSION_NUMBER无法转换为字符串),int()方法将为您引发ValueError,您可以按如下方式进行检查:
@version.setter
def version(self, version_number):
try:
version_number = int(version_number)
except ValueError: #when casting to int fails, Python raises a ValueError
# handle error here
#otherwise, version_number is now a valid int, so continue
If you're the only one that will be using your code, you can forgo this validation at your own risk. Regardless of which you choose, it's also a good idea to use type hints. Type hints don't do anything at runtime (so they won't perform any casting/validation for you), but can help assist your IDE in reminding you what type is expected for a parameter or return. Type hints for your function might look as follows:
如果您是唯一将使用您的代码的人,您可以放弃此验证,风险自负。无论您选择哪种类型,使用类型提示都是一个好主意。类型提示在运行时不做任何事情(因此它们不会为您执行任何强制转换/验证),但可以帮助您的IDE提醒您参数或返回应该使用什么类型。为您的函数键入提示可能如下所示:
@version.setter
def version(self, version_number: int) -> None:
No type hint is required on the self
parameter, as your IDE can tell self
will be an ExampleObject
. The type hint int
on the parameter version_number
indicates that this parameter should be an int. Finally, the return type hint of None
indicates this function doesn't return anything.
在self参数上不需要类型提示,因为您的IDE可以告诉您self将是一个ExampleObject。参数VERSION_NUMBER上的类型提示指示此参数应为int。最后,返回类型提示NONE表示该函数不返回任何内容。
Source: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
消息来源:https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
更多回答
Hey, apologies but I forgot to mention that I can only use python 2 for my code so type hints are not an option. Also, isn't casting doing the same thing of enforcing type in a round-a-bout way? One way or another, I am still enforcing it so why not use the less expensive isinstance()?
嘿,对不起,我忘了提一下,我的代码只能使用python2,所以不能使用类型提示。此外,演员阵容不是在以一种轮流的方式强制执行类型吗?不管怎样,我仍然在执行它,所以为什么不使用更便宜的isInstance()呢?
I have decided to drop python 2 and use python 3 but my question over the casting is still there. So let me know what you think about it.
我已经决定放弃python2而使用python3,但我对造型的问题仍然存在。所以,让我知道你对它的看法。
@Parikshit It depends on how you want to handle the error. If you want to raise a ValueError with a custom message (to either show in the console or handle while calling the method), your original method works. If you'd rather handle it gracefully inside the method, you can use the try/catch paradigm to avoid an uncaught exception.
@巴黎狗屎这取决于你想要如何处理错误。如果您希望使用自定义消息引发ValueError(以便在调用方法时显示在控制台或句柄中),则可以使用原始方法。如果您更愿意在方法中优雅地处理它,可以使用Try/Catch范例来避免未捕获的异常。
Got it. Thanks for the help.
明白了。谢谢你的帮助。
我是一名优秀的程序员,十分优秀!