常见自带魔术变量

__dict__

  • 用于显示出实例的属性
    实例 自身的 命名空间字典,存储该类或实例 直接定义的所有属性和方法

  • 对于类对象
    包含类层级上的所有 属性、方法、元类、继承关系 等。

  • 对于实例对象
    包含实例层级上的所有 动态添加的属性(不包括类定义的属性和方法)。

    比如:

    1
    print(().__class__.__bases__[0].__subclasses__()[94].__dict__)

    这里将原型__subclasses__()[94]所有的属性以字典形式列出

  • 举个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Person:
    species = "human" # 类变量
    def __init__(self, name):
    self.name = name # 实例变量

    def greet(self):
    return f"Hello, {self.name}"

    print(Person.__dict__) # 输出示例如下:
    # {
    # 'species': 'human',
    # '__init__': <function Person.__init__>,
    # 'greet': <function Person.greet>, 即前面的Person为该类的名字,greet为该类中的一个函数
    # ...
    # }

    # 注意:实例变量(如 name)不在此字典中,属于实例的 __dict__

__init__.__globals__["builtins"]

  • 它是一个字典,包含了 整个 Python 模块运行时的所有全局变量和导入的模块。

  • 以下是一段帮助我们辨析理解的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import os
    global_var = "I'm a global variable"

    class MyClass:
    class_attr = "I'm a class attribute"

    def __init__(self, instance_attr):
    self.instance_attr = instance_attr

    def method(self):
    pass

    _class = MyClass("Hello, world!")

    # 查看类的__dict__
    print(MyClass.__dict__) # 输出类本身的定义内容
    print("\n")
    print(_class.__dict__) # 输出实例的__dict__(只会包含实例属性)
    print("\n")
    print(MyClass.__init__.__globals__)
    print("\n")
    print(MyClass.__init__.__globals__["__builtins__"])
  • 这里的print(MyClass.__init__.__globals__)的结果为:

    1
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002660053BC50>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'i:\\.python小脚本\\web\\ssti\\test.py', '__cached__': None, 'MyClass': <class '__main__.MyClass'>, '_class': <__main__.MyClass object at 0x0000026600738A40>}
  • 即为该python模块,通俗来说就是这个python代码文件的所有导入模块以及变量等属性。

关于__globals__["__builtins__"]输出结果的解释

  • 个人最为疑惑的就是为什么有时对该类的__init__.__globals__["__builtins__"]进行打印只会回显:
    <module 'builtins' (built-in)>,因为此时该类中对__builtins__模块的引用属于直接引用,并没有呈字典形式在类中引用。
    而有些python自带类则以字典形式对__builtins__模块中的方法进行引用,所以打印该键所代表值可以得到大量键值对数据。

杂项疑点

关于寻找eval函数以及寻找popen的区别

  • 为什么寻找前者需要在子类的__subclasses__()[i].__init__.__globlas__['__builtins__']中寻找,后者只需在:
    __subclasses__()[i].__init__.__globlas__中寻找?
  • 原因在于,eval为python自带模块中的方法,所以需要再在每个类自动引入的[__builtins__]模块中寻找,而popen方法并不属于__builtins__类,所以不需要在该模块中寻找,直接在全局变量中寻找。