python - 如果您不信任全局变量,那么当您在一个方法内部时,您如何判断我们当前在哪个类中?
问题描述
这是一个关于内省的一般原则的问题。当您在一个方法中时,我们如何才能知道我们当前在哪个类中?
我们想要如下内容:
class FigNewton:
def baz(self):
current_class = MAGIC()
会MAGIC
是什么?以下是不可接受的,因为我们在调用时全局变量不受信任的环境中工作。定义时的全局变量是可信的,但在方法调用时不是全局变量。
class FigNewton:
def baz(self):
current_class = FigNewton
为什么全局变量在调用时不受信任?因为有下面这样的恶作剧:
class FigNewton:
def baz(self):
current_class = FigNewton
print("banana")
print("current_class ==", current_class.__name__)
import itertools
import string
print = lambda *args, print=print:\
print(
sum(
map(
lambda stryng:\
int(''.join(
itertools.takewhile(
lambda ch: ch in string.ascii_lowercase
,
stryng
)
), base=36)
,
map(str, args)
)
, )
)
print("apple")
obj = FigNewton()
FigNewton = "apple"
obj.baz()
输出是:
17995730
683010982
27999997387
而不是预期的:
apple
banana
current_class == FigNewton
下面是更多演示问题的代码:
class K0:
print=print
type=type
def foo(self, *args):
self.print(40 * "--")
self.print('args == ', args)
self.print("K0 version of foo is executing.")
self.print("Are all references to class K0 lost?")
self.print("Well, global label `K0` is ", self.type(K0).__qualname__, K0)
# K0.__getattribute__(self, "whatever") ## ERROR!!!
tsqn = self.type(self).__qualname__
self.print(
"type(self) is ", tsqn,
". Is that K0? ", ("yes" if tsqn == "K0" else "no"),
sep=""
)
self.print(40 * "--")
##########################################################
def test(seed_class):
Ks = [seed_class]
for idx in (1, 2, 3):
K = type("K{}".format(idx), (Ks[-1],), dict())
Ks.append(K)
class K4(Ks[-1]):
def foo(self):
print("K10 version of foo is executing")
print("type(self) is ", type(self))
# Begin messing up global namespace
global K0
K0 = 0
# End messing up global namespace
Ks.pop(0)
for K in Ks:
obj = K()
obj.foo(1, 2, 3)
return None
##########################################################
test(K0)
输出是:
--------------------------------------------------------------------------------
args == (1, 2, 3)
K0 version of foo is executing.
Are all references to class K0 lost?
Well, global label `K0` is int 0
type(self) is K1. Is that K0? no
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
args == (1, 2, 3)
K0 version of foo is executing.
Are all references to class K0 lost?
Well, global label `K0` is int 0
type(self) is K2. Is that K0? no
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
args == (1, 2, 3)
K0 version of foo is executing.
Are all references to class K0 lost?
Well, global label `K0` is int 0
type(self) is K3. Is that K0? no
--------------------------------------------------------------------------------
解决方案
在 CPython 引用解释器中,您可以通过简单地引用来获取定义方法的类__class__
:
class FigNewton:
def baz(self):
current_class = __class__ # Assigns FigNewton, even if instance of subclass is used to invoke method
据我所知,这是 CPython 的一个实现细节(它用于支持无参数super()
调用,我认为除了在更改日志和 What's New 文档中传递之外没有提到它),所以不要依赖它在其他口译员上。
如果您想要运行时类型(因此即使在父类中定义的方法中调用它也会报告子类类型),请使用type(self)
(或等效地,self.__class__
):
class FigNewton:
def baz(self):
current_class = type(self) # Assigns FigNewton or a subclass thereof if instance of subclass is used to invoke method
推荐阅读
- php - Yii2如何将表单请求发送到外部url
- c++ - 双向链表 std::unique_ptr 类在节点删除时无法按预期工作
- powershell - 搜索 txt 文件,如果字符串存在则返回 PC 名称
- html - 调整浏览器大小时的响应问题
- c# - StackPanel 中的 TextWrap
- c++ - 模拟工厂的初始化没有匹配的构造函数
- python-3.x - 减少python中的图像尺寸
- javascript - 如何在不影响其他下拉菜单的情况下多次使用状态下拉菜单和城市下拉菜单
- windows - 如何查看所有任务的 Windows 计划任务历史记录?
- c++ - 自动排除如何与带有嵌套小部件的 QRadioButtons 一起使用?