【问题标题】:Is it "OK" to just start adding attributes to Skyfield objects?刚开始向 Skyfield 对象添加属性是否“可以”?
【发布时间】:2016-05-06 22:42:37
【问题描述】:

这里,“OK”当然是指 AYOR(风险自负),但如果避免与现有属性名称发生明显冲突,则不会出现可预见的问题。

Skyfield 对象——尤其是行星——通常具有有限数量的属性。我经常编写简短的脚本来提取我保存为文本并稍后使用的数字数据。 这些基本上是“一次性”脚本,因为我很少使用它们超过一次或两次,并且从不分享它们。

当我编写更持久的代码时,我当然会创建自己的容器对象。

我的问题:这对我来说似乎效果很好,所以在这个特定的上下文中,除了属性冲突之外,还有什么可能出错名字

from skyfield.api import load
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

eph   = load('de421.bsp')
earth = eph['earth']
sun   = eph['sun']

ts = load.timescale()

t  = ts.utc(2016, 1, np.linspace(0, 366, 1000))

# SLOPPY WAY: just add them directly
earth.pos  = earth.at(t).position.km
sun.pos    = sun.at(t).position.km
earth.r    = np.sqrt(((earth.pos-sun.pos)**2).sum(axis=0))
earth.peri = earth.r.min()
earth.apo  = earth.r.max()

print earth.peri, earth.apo, earth.pos.shape


# BETTER WAY: tedious but more cautious
uhoh  = dict()
ep    = earth.at(t).position.km
sp    = sun.at(t).position.km
r     = np.sqrt(((ep-sp)**2).sum(axis=0))
uhoh['pos']  = ep
uhoh['r']    = r
uhoh['peri'] = r.min()
uhoh['apo']  = r.max()
earth.uhoh   = uhoh

print earth.uhoh['peri'], earth.uhoh['apo'], earth.uhoh['pos'].shape

返回:

147100175.99 152103762.948 (3, 1000)
147100175.99 152103762.948 (3, 1000)

【问题讨论】:

  • 向对象添加任意元素几乎总是一个坏主意,除非该类是专门为它设计的。这可能会在以后以可怕的方式破裂。你为什么要这样做?如果必须,更好的方法是创建自己的容器类来包装天空对象,并包含任何您想要携带的与它相关联的附加属性。
  • @uhoh 这有点好,因为它有助于避免名称冲突(从技术上讲,您只是添加一个属性)。但我仍然同意@Iguananaut;创建一个容器类,该类在其构造函数中接受一个天空对象,并计算您需要的任何值并将其分配给实例变量。
  • @pzp 那么我们都同意这一点,谢谢!但是如果我这样做了,除了属性名冲突之外,还有其他可能出错的地方吗?我不知道的python更深一点的东西?这是我的问题。我是优秀编程的拥护者,但我仍然对可能出现的问题抱有一种病态的好奇心。
  • 对于大多数 Python 对象,什么都没有。分配不存在的属性只是obj.__dict__[attr] = val 的快捷方式,除非对象正在使用槽,或者已覆盖__setattr__

标签: python skyfield


【解决方案1】:

这确实是一种在非正式 Python 代码中偶尔会遇到的模式。除了未来的属性名称冲突之外,另一个可能出错的主要事情是库作者在想要更有效地创建数百万个对象的人的怂恿下,添加了__slots__ 规范,当您开始收到错误时您尝试添加其他属性。

如果出现__slots__,防御是使用您自己想要使用的类的子类。如果一个子类也没有指定__slots__——至少说__slots__ = [],即使它没有更多要添加的属性——那么子类的实例是完全开放的,可以有任何属性,所以你总是可以创建一个子类您自己的“解锁”实例并让它们具有任何属性。

请注意,像 earth 这样的对象有资格成为字典键,因此,如果您想将一条信息与每个行星相关联,您可以这样说:

positions = {}
positions[earth] = ...

当您需要记住有关一组对象中的每一个的额外信息时,这是一种常见的模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多