简体   繁体   English

在Python中将对象从类转换为子类的方法

[英]Method to convert object from class to subclass in Python

Consider the following minimal problem: 考虑以下最小问题:

from math import sqrt    

class Vector(object):

    def __init__(self, x, y, z):
        self.v = [x, y, z]

    def normalize(self):
        x, y, z = self.v
        norm = sqrt(x**2 + y**2 + z**2)
        self.v = [x/norm, y/norm, z/norm]

    # other methods follow  

class NormalizedVector(Vector):

    def __init__(self, x, y, z):
        super(Vector, self).__init__(x, y, z)
        self.normalize()

So essentially NormalizedVector objects are the same as Vector objects but with the added normalization. 因此,NormalizedVector对象基本上与Vector对象相同,但添加了规范化。

Would it be possible to add a method to Vector so that whenever the normalize method is called the object is automatically subclassed to NormalizedVector? 是否可以向Vector添加一个方法,以便每当调用normalize方法时,对象都会自动子类化为NormalizedVector?

I know that I could be using the abstract factory pattern , but this would only work if objects are subclassed at creation: I would like to be able to subclass objects that have already been created previously. 我知道我可以使用抽象工厂模式 ,但这只有在创建时对象被子类化时才会起作用:我希望能够创建先前已创建的对象的子类。

I have found some solutions based on reassigning the __ class __ method, but these are discouraged. 我找到了一些基于重新分配__ class __方法的解决方案 ,但不鼓励这些。 I am willing to modify the pattern above to a one that it is more "Pythonic". 我愿意将上面的模式修改为更“Pythonic”的模式。

I would recommend to use only the Vector() class and with a boolean normalized instance attribute. 我建议只使用Vector()类和布尔normalized实例属性。

Also, in normalize method you are using x , y and z but those variables are not defined and you are not even reading them with self . 此外,在normalize方法中,您使用的是xyz,但这些变量未定义,您甚至无法使用self读取它们。

The code I would recommend: 我建议的代码:

from math import sqrt    

class Vector(object):

    def __init__(self, x, y, z, normalized=False):
        self.v = [x, y, z]
        if normalized in [True, False]:
            self.normalized = normalized
        else:
            raise Exception("Please set normalized to either True or False")

    def __repr__(self):
        return "Vector ({}, {}, {})".format(*self.v)

    def normalize(self):
        x,y,z = self.v
        norm = sqrt(x**2 + y**2 + z**2)
        self.v = [x/norm, y/norm, z/norm]
        self.normalized = True

    def isNormalized(self):
        return self.normalized

    # other methods follow  

v1 = Vector(10, 20, 30)
print v1.isNormalized()
v1.normalize()
print v1.isNormalized()

v2 = Vector(40, 50, 60, normalized=True)
print v2.isNormalized()

Output: 输出:

False
True
True


The __repr__ function will just show a good representation of your object: __repr__函数只显示对象的良好表示:

print v1

Output: 输出:

Vector (0.267261241912, 0.534522483825, 0.801783725737)

Why do you need to keep track of the normalization in the vector itself, just keep track of it in your main.py or wherever you're using the vectors? 为什么需要跟踪向量本身的规范化,只需在main.py或在使用向量的任何地方跟踪它?

Also, I would simply return a new copy of the object with the normalized values. 此外,我只是返回具有规范化值的对象的新副本。 This way you can create normalized vectors on the fly in your calculations without changing the original vector. 这样,您可以在计算中动态创建规范化矢量,而无需更改原始矢量。

from math import sqrt    

class Vector(object):

    def __init__(self, x, y, z):
        self.v = [x, y, z]

    def normalized(self):
        x, y, z = self.v
        norm = sqrt(x**2 + y**2 + z**2)
        return Vector(x/norm, y/norm, z/norm)

If you have really many vectors you need to normalize, you can normalize them into two lists or a list of tuples or whatever you want, here's a dict example: 如果你有很多向量需要规范化,你可以将它们规范化为两个列表或一个元组列表或任何你想要的,这是一个dict示例:

vectors = {}
for x, y, z in zip(range(10), range(10), range(10)):
    v = Vector(x, y, z)
    vectors[v] = v.normalize()

If you just have a few vectors or randomly need to normalize a vector for a calculation every now and then, you can just keep track of them manually or create them on the fly in the calculations without changing the original vector: v_norm = v.normalized() . 如果您只是有一些向量或随机需要对矢量进行标准化以进行计算,您可以手动跟踪它们或在计算中动态创建它们而不更改原始向量: v_norm = v.normalized()

If you really want to keep the two classes you could overwrite the operations for the classes. 如果你真的想保留这两个类,你可以覆盖类的操作。

Let's say you want to add the vector and the normalized vector. 假设您要添加向量和规范化向量。 You could do it like this 你可以这样做

from math import sqrt 来自math import sqrt

class Vector:

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def __add__(self,v):
        if isinstance(v,Vector):
            return (self.x+v.x,self.y+v.y)
        elif isinstance(v,NormVector):
            n = NormVector(self.x,self.y)
            return (n.x+v.x,n.y+v.y)

class NormVector:

    def __init__(self,x,y):
        self.x = x / sqrt(x**2 + y**2)
        self.y = y / sqrt(x**2 + y**2)

    def __add__(self,v):
        if isinstance(v,Vector):
            n = NormVector(v);
            return (self.x + n.x,self.y + n.y)
        elif isinstance(v,NormVector):
            return (self.x+v.x,self.y+v.y)


a = Vector(5,0)
b = NormVector(0,3)
c = a + b
print c

Like this you can overwrite any function you need. 像这样你可以覆盖你需要的任何功能。 A list of possible operations can you find in the documentation 您可以在文档中找到可能的操作列表

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

相关问题 自动将对象从类转换为子类 - convert object from class to subclass automatically 父类的Python子类调用方法 - Python subclass invoking method from parent class Parent Class with new object, and new object in Subclass, object/method inheritance Python - Parent Class with new object, and new object in Subclass, object/method inheritance Python Python 类从类对象调用方法 - Python class call a method from a class object Python 方法返回 class 或子类的实例,同时保留子类属性 - Python method that returns instance of class or subclass while keeping subclass attributes 将 function 包装为 python 中 class 的子类中的方法 - wrap a function as a method in a subclass of a class in python 如何将通过重写方法从子类计算的值返回到python中的基类方法 - How to return a value computed by overriding method from a subclass to it's base class method in python 是否可以从python中的对象(而不是类)中删除方法? - Is it possible to delete a method from an object (not class) in python? Python - 如何通过使用子类中的自定义参数调用来重用抽象 class 中的方法? - Python - How to reuse a method from an abstract class by calling with a custom parameter from a subclass? Python,从抽象基调用子类方法 - Python, calling subclass method from abstract base
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM