Python类 - 使用实例作为属性

3

我目前正在学习/使用Python 3.10.2中的类。我的目标是创建一个类实例,该实例是另一个类的属性。

以下是我编写的一些代码,以帮助说明我的观点。

class Vehicle():
    """To model a basic vehicle"""
    def __init__(self, name, max_speed, millage):
        """Initiate class variables"""
        self.name = name
        self.max_speed = max_speed
        self.millage = millage
        self.tyre = Tyre()

    def vehicle_details(self):
        """display vehicle details"""
        return f"\nName: {self.name.title()}, Max speed: {self.max_speed}MPH, Millage: {self.millage} "

class Tyre():
    """A class specific for vehicle tyres"""
    def __init__(self, size=16, pressure=36):
        self.size = size
        self.pressure = pressure

    def tyre_details(self):
        """Print tyre details."""
        print(f'Tyre size: {self.size} inches.')
        print(f"Tyre pressure {self.pressure} PSI.")

Vehicle类中,我将Tyre()添加为属性。
现在这段代码确实可以工作,并且我可以通过我的Vehicle实例调用Tyre方法,但只有在Tyre类内分配了预定值给 sizepressure 时才可以。
是否存在以下两种情况之一:
  1. A way I can achieve this without having to allocate the pre-determined values within the Tyre class?

    This is the Traceback I receive if I do not allocate the pre-determined values:

    TypeError: __init__() missing 2 required positional arguments: 'size' and 'pressure'
    
  2. An easy way for me to overwrite the pre-determined values when calling this class and its methods if I am unable to remove the pre-determined values?


你应该先在谷歌上搜索Python中的对象创建和构造函数,那将是第一件要查找的事情。基本上,你的车辆还需要使用特定的轮胎尺寸和压力值才能具有正确的轮胎价值,如果这有任何意义的话。因此,你应该将sizepressure参数添加到车辆类构造函数中,如:def __init__(self, name, max_speed, millage, tyre_size, tyre_pressure),并在创建时将它们传递给轮胎:self.tyre = Tyre(tyre_size,tyre_pressure) - Abhigyan
我不确定这与“Vehicle”类有什么关系。当您仅独立使用“Tyre”类时,您是否也会有同样的疑问? - mkrieger1
4个回答

6
  1. 有没有不必在Tyre类中分配预定值就可以实现这一点的方法?

一个可能的解决方案是,在初始化Vehicle时传递Tyre的参数:

class Vehicle:

    def __init__(self, name, max_speed, millage, tyre_size=16, tyre_pressure=36):
        """Initiate class variables"""
        self.name = name
        self.max_speed = max_speed
        self.millage = millage
        self.tyre = Tyre(size=tyre_size, pressure=tyre_pressure)

如果我无法删除预设值,如何在调用这个类和其方法时轻松地覆盖预设值?你可以简单地不使用任何预设值,要求明确提供它们:
class Tyre:

    def __init__(self, size, pressure):
        # ...

如果没有传递任何值,会引发异常。只有在真正需要时,您才应该依赖预定的值。而不是总是依赖一组特定的预定值。

通常情况下,我建议仅在很少需要与默认值不同的值时使用预定的值。例如,如果您有一个User类,可能您总是使用不同的username。没有明显的默认值。另一方面,当您拥有一个Vehicle类时,在大多数情况下它将拥有4个门,但有时可能会有所不同(也许是5),因此您可以将4作为默认值并在需要时更改它。


3

有无数种方法来“解决”这个问题,但我会介绍几种。

没有“正确”的方法,所有方法都涉及权衡,在一段时间内,您将学会在哪些情况下使用哪种方法。

传递参数

class Vehicle():
    """To model a basic vehicle"""
    def __init__(self, name, max_speed, millage, tyre_size, tyre_pressure):
        """Initiate class variables"""
        self.name = name
        self.max_speed = max_speed
        self.millage = millage
        self.tyre = Tyre(tyre_size, tyre_pressure)

    def vehicle_details(self):
        """display vehicle details"""
        return f"\nName: {self.name.title()}, Max speed: {self.max_speed}MPH, Millage: {self.millage} "


class Tyre():
    """A class specific for vehicle tyres"""
    def __init__(self, size, pressure):
        self.size = size
        self.pressure = pressure

    def tyre_details(self):
        """Print tyre details."""
        print(f'Tyre size: {self.size} inches.')
        print(f"Tyre pressure {self.pressure} PSI.")

v1 = Vehicle("VehicleName", 120, 50_000, 16, 36)
# Or, with named arguments
v2 = Vehicle(
    name = "VehicleName", 
    max_speed = 120, 
    millage = 50_000, 
    tyre_size = 16, 
    typre_pressure = 36
)

在这里,你只是从Vehicle构造函数将参数传递给了Tyre的构造函数来构建Tyre。如果每次构造一个Vehicle时都知道Tyre的规格,那么这样做就没问题。如果不知道,你可能需要另一种方法。

使用Tyre实例作为参数构造Vehicle

class Vehicle():
    """To model a basic vehicle"""
    def __init__(self, name, max_speed, millage, tyre):
        """Initiate class variables"""
        self.name = name
        self.max_speed = max_speed
        self.millage = millage
        self.tyre = tyre

    def vehicle_details(self):
        """display vehicle details"""
        return f"\nName: {self.name.title()}, Max speed: {self.max_speed}MPH, Millage: {self.millage} "


class Tyre():
    """A class specific for vehicle tyres"""
    def __init__(self, size, pressure):
        self.size = size
        self.pressure = pressure

    def tyre_details(self):
        """Print tyre details."""
        print(f'Tyre size: {self.size} inches.')
        print(f"Tyre pressure {self.pressure} PSI.")


v = Vehicle(
    name = "VehicleName", 
    max_speed = 120, 
    millage = 50_000, 
    tyre = Tyre(16, 36)
)

与前一个选项类似,但在前一个选项中,每个 Vehicle 都有自己的 Tyre 实例。 在这里,您可以“共享”Tyre对象。 在这种情况下可能不是很重要,但是需要牢记,特别是当您使用更大或更复杂的对象并/或共享成为一个好处时。
共享 Tyre 实例可能如下所示:
standard_tyre = Tyre(16, 36)

v1 = Vehicle(
    name = "VehicleOne", 
    max_speed = 120, 
    millage = 50_000, 
    tyre = standard_tyre,
)
v2 = Vehicle(
    name = "VehicleTwo", 
    max_speed = 140, 
    millage = 20_000, 
    tyre = standard_tyre,
)

在构造函数之外设置轮胎

class Vehicle():
    """To model a basic vehicle"""
    def __init__(self, name, max_speed, millage):
        """Initiate class variables"""
        self.name = name
        self.max_speed = max_speed
        self.millage = millage
        self.tyre = None

    def vehicle_details(self):
        """display vehicle details"""
        return f"\nName: {self.name.title()}, Max speed: {self.max_speed}MPH, Millage: {self.millage} "


class Tyre():
    """A class specific for vehicle tyres"""
    def __init__(self, size, pressure):
        self.size = size
        self.pressure = pressure

    def tyre_details(self):
        """Print tyre details."""
        print(f'Tyre size: {self.size} inches.')
        print(f"Tyre pressure {self.pressure} PSI.")


v = Vehicle(
    name = "VehicleName", 
    max_speed = 120, 
    millage = 50_000, 
)
v.tyre = Tyre(16,36)

也许在创建 "Vehicle" 时,您不知道 "Tyre" 的具体细节,但仍然想要一个 "Vehicle" 实例。

0

在创建 Tyre 类的实例时,您可以设置参数。当没有传入参数时,预设值才会被使用,因此如果您这样做 self.tyre = Tyre(轮胎尺寸, 轮胎压力),它将不会使用预设值。


-1
我在您的代码后面运行了以下内容,对我来说它很好地工作了。
veh = Vehicle('Volkswagen', 200, 10)
print(veh.tyre.tyre_details())

输出:

Tyre size: 16 inches.
Tyre pressure 36 PSI.

通过车辆实例覆盖轮胎尺寸和压力:
veh.tyre.size = 17
veh.tyre.pressure = 38
print(veh.tyre.tyre_details())

输出

Tyre size: 17 inches.
Tyre pressure 38 PSI.

也许你正在错误地访问轮胎实例。

是的,这也是我得到的结果。但是,如果我删除预设值,即使包括:veh.tyre.size = 17 等等,它也不起作用。 - ScottMButler
如果您删除了预设值,那么您就没有为Tyre类提供所需的参数。那么以上某些答案就可以了。 - Hrishikesh Nadkarni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接