我写过C#并且来自高处的口头禅似乎“从不在生产代码中使用反射”。我已将它用于测试代码,但从未在野外运行过。所有的论点看起来都是合理的,总有一种方法可以通过添加另一层抽象或设计模式或其他方式来实现。
现在我开始编写一些严肃的Python代码,我想知道是否适用相同的原则。似乎python的设计考虑了反思。模块和类将成员存储在易于访问的字典中。 Django的模型的Meta类,例如将字符串作为引用成员。
我可以在Python中编写C#/ Java,但我真的不想这样做。我仍然坚信所说的语言“没有反思”。 Python的方式是根本不同的吗?
答案 0 :(得分:16)
作为一种动态语言,Python与静态类型语言根本不同,所以一切都在其中反映:-)而且从不在生产代码中使用反射(对于静态语言)对我来说似乎有点极端
答案 1 :(得分:6)
我认为c#中的“生产代码中没有反映”是不正确的 反思通常允许程序员做其他事情不可能的事情 我会说“在生产代码中没有反映非公开成员”和“谨慎使用反思!”如果使用不当,可能会失去性能。正确使用可以让你获得性能(只考虑静态反射) 不要将反射用于大规模调用的代码 而Python则是一种动态语言。所有概念都不同。正常性(以及正确的方法)是使用您正在谈论的技术。
答案 2 :(得分:2)
是的,在这方面,Python开发 基本不同。
C#/ Java中的反思是指运行时能够了解正在运行的代码的事情,并根据该信息做出决策。
由于Python使用动态类型,任何类型的发现都被委托给运行时而不是编译时,所以基本上这意味着任何 Python程序必须使用反射才能工作,只有它不是叫反映,它叫做运行程序:) 此外,Python哲学包含了执行的动态特性,因此您应该毫不犹豫地利用它来为您带来优势。
P.S。虽然应该避免在紧密循环中使用反射,并且应该意识到反射慢一到两个数量级,但是当它是正确的工具时,不应该害怕使用反射。
答案 3 :(得分:0)
IMO我之所以避免在生产代码中使用反射是因为反射可能会使代码难以维护和调试。
答案 4 :(得分:0)
反思是非常先进和强大的技术。但它很慢。你可以使用反射,但不能经常使用反射。 因此,CLR开发人员为.NET 4.0添加了一个更酷的类型 - 动态类型。我强烈建议您参考一些文档或书籍以获取更多信息。 F.E. CLR通过C#。
dynamic a = SomeFooInterface.GetsomeObjectWithUnknownInterface();
// returns object, for example, from another assembly. or some unknown instance.
// But you know that there is method int GetValue() inside.
// So you can call this method without any casts!
int myValue = a.GetValue();
// This method is much faster then reflection!
CLR通过C#:
也有很多场合 程序必须对信息采取行动 它直到它才知道 运行。虽然你可以使用类型安全 编程语言(如C#) 与此信息互动, 语法往往是笨拙的,特别是 因为你倾向于工作很多 字符串和性能受到阻碍 同样。如果你正在写一个纯粹的C# 申请,那么唯一的场合 你有工作 运行时确定的信息是何时 你正在使用反射(讨论在 第23章)。 然而,许多开发人员 也使用C#进行通信 未实现的组件 C#。其中一些组件可能是 .NET动态语言,如Python 或Ruby ,或支持的COM对象 IDispatch接口(可能 在本机C或C ++中实现),或 HTML文档对象模型(DOM) 对象(使用各种实现 语言和技术)。 与HTML DOM对象进行通信 建立一个特别有用的 Microsoft Silverlight应用程序。至 使开发人员更容易使用 反思或与他人沟通 组件,C#编译器为您提供 一种将表达式类型标记为的方法 动态。你也可以把结果 表达式变量和变量 您可以将变量的类型标记为 动态。这种动态 然后可以使用表达式/变量 调用诸如字段之类的成员 property / indexer,方法,委托, 和一元/二元/转换运算符。 当您的代码使用时调用成员 动态表达式/变量, 编译器生成特殊的IL代码 描述了所需的操作。 这个特殊代码称为 有效载荷。 在运行时,有效负载 代码确定了确切的操作 根据实际类型执行 现在引用的对象 动态表达/变量。