简体   繁体   English

Python中内置类型的多态性

[英]Polymorphism with built-in types in Python

I have a collection of variables in Python, some of which are normal Python numbers and some of which are instances of a class I've written called Property, which represents a range of possible values (eg between 0 and 4.2). 我在Python中有一些变量集合,其中一些是普通的Python数字,其中一些是我编写的一个名为Property的类的实例,它表示一系列可能的值(例如0到4.2之间)。 I want to iterate over this collection and do something different depending on whether each item is a built-in number or a Property. 我想迭代这个集合并根据每个项目是内置数字还是属性来执行不同的操作。 Of course I could do this by explicitly checking the type, but I want to know if there's a clean, object-oriented, idiomatic way to do it in Python. 当然,我可以通过显式检查类型来做到这一点,但我想知道在Python中是否有一个干净的,面向对象的惯用方法。

For example, one of the things I want to do depends on the signs of the collection's entries, so I want to write a function that returns the sign of its argument, regardless of whether it's passed a built-in type or a Property. 例如,我想要做的事情之一取决于集合条目的符号,所以我想编写一个返回其参数符号的函数,无论它是通过内置类型还是属性。 I can add a __sign__ method to Property, but there's no __sign__ method for built-in numeric types, and Python won't let me add one, so that doesn't help. 我可以向Property添加一个__sign__方法,但内置数值类型没有__sign__方法,Python也不会让我添加一个,所以这没有帮助。

Perhaps I'm just making a mistake by having a collection that mixes class instances with built-in types - but changing it would clutter my code's interface. 也许我只是通过一个将类实例与内置类型混合在一起的集合来犯错 - 但改变它会使我的代码界面变得混乱。 Instead of writing 而不是写作

myList = [0, 2.3, 4, Property(0,2)]

I'd have to write something like 我必须写一些类似的东西

myList = [Property(0), Property(2.3), Property(4), Property(0,2)]

which I'd prefer to avoid if possible. 如果可能的话,我宁愿避免。

Here's some more information about what I'm trying to do. 这里有一些关于我正在尝试做什么的更多信息。 I'm working on a scientific problem that involves keeping track of a lot of variables, which interrelate in particular ways. 我正在研究一个涉及跟踪许多变量的科学问题,这些变量以特定的方式相互关联。 A lot of these variables have known values (because they've been measured) but some are unknown and others have been measured but not accurately, so we know they must lie in some particular range. 很多这些变量都有已知的值(因为它们已被测量)但有些是未知的,有些已被测量但不准确,因此我们知道它们必须位于某个特定范围内。 There are equations that specify the interrelationships between these variables, and ultimately I will use a numerical optimisation library to find the possible ranges of the unknown variables. 有些方程式指定了这些变量之间的相互关系,最终我将使用数值优化库来查找未知变量的可能范围。

Because there are a lot of variables I want to store all the known data about them in a sensibly formatted input file. 因为有很多变量我想在一个合理格式化的输入文件中存储有关它们的所有已知数据。 Although I want to keep this a python file for simplicity, it's important to keep its syntax as simple as possible, both for my sake and because it might have to be read or added to by non-programmers. 虽然为了简单起见我想保留这个python文件,但为了我的缘故,保持其语法尽可能简单是非常重要的,因为它可能必须由非程序员读取或添加。 Currently it has lots of lines that look something vaguely like this: 目前它有很多行看起来像这样模糊:

a.set_some_parameters(3.2, -1, Property(2.3,2.5))
a.x = 0.1
b.x = Property.unknown()
a.set_some_other_parameters(Property.positive(), -4.2, 1, 0)

The point being that (pretty much) anywhere you can enter a number, you can instead enter a Property if the value isn't precisely known. 关键在于(几乎)你可以输入一个数字,如果值不准确,你可以输入一个属性。 This works well as an interface, but I end up in the situation described above, where my code continually has to deal with the fact that something might be a built-in number, or it might be a Property instance. 这很适合作为一个接口,但最终我遇到了上述情况,我的代码不断处理某些东西可能是内置数字的事实,或者它可能是一个Property实例。

Without knowing enough about what you're doing, I'm going to go ahead and agree with your statement 如果不了解你正在做什么,我会继续并同意你的陈述

Perhaps I'm just making a mistake by having a collection that mixes class instances with built-in types 也许我只是通过一个将类实例与内置类型混合在一起的集合来犯错误

If you only need to compare the sign between built-in numbers and your Property instances, it wouldn't be such a big deal (use the cmp function and override comparison operators on your Property class), but I'm betting that's not all you want to do. 如果你只需要比较内置数字和你的属性实例之间的符号,它就不会那么大(使用cmp函数并覆盖你的Property类上的比较运算符),但我打赌这不是全部你想做什么。

Instead, think of better ways to construct your list, if that's what you're really worried about. 相反,想一想更好的方法来构建你的列表,如果那是你真正担心的。 Here's two examples: 这是两个例子:

P = Property
myList = [P(0), P(2.3), P(4), P(0,2)]

# or...

def createPropertyList(*args):
    return [Property(x) for x in args]

myList = createPropertyList(0,2.3,4,(0,2))

From the design point of view you are doing something odd. 从设计的角度来看,你正在做一些奇怪的事情。 If you have a list of things and you want to act on them they do share something! 如果你有一系列的东西,并且你想对它们采取行动,那么它们会分享一些东西!

So, you should think about what should be their common interface. 所以,你应该考虑他们的共同界面应该是什么。

You have some different solutions: 你有一些不同的解决方案:

-as you suggest you could define a new constructor for Property that takes the built-in, - 如果你建议你可以为Property定义一个新的构造函数来获取内置的,

-if you want your object to still be an integer you can make a subclass of integers, - 如果你希望你的对象仍然是一个整数,你可以创建一个整数的子类,

-you can also define a new class that has an integer member, then you can define the methods of your new class so to define an appropriate interface for your integer. - 您还可以定义具有整数成员的新类,然后可以定义新类的方法,以便为整数定义适当的接口。 In other words you wrap your integer in a new class. 换句话说,您将整数包装在一个新类中。

Please, do something for having the appropriate shared interface for the objects in your list. 请为列表中的对象提供适当的共享接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM