PHP 和 Python 速查手册
部署方式
PHP 的部署方式
PHP 程序有如下几种运行方式:
- CGI
- FastCGI
- ISAPI Extension
- Apache Mod
其中,CGI 和 FastCGI 以进程的方式运行,使用 nts(非线程安全)版本; ISAPI Extension 和 Apache Mod 以线程方式运行在宿主进程(IIS进程或Apache进程)内,使用 ts(线程安全)版本。
以上几种方式以 FastCGI 最为常见。PHP 5 自带的 php-cgi 可以直接运行 FastCGI 服务。不过在生产环境中,一般使用 PHP-FPM 作为 FastCGI 的进程管理工具。
Nginx + FastCGI 方式配置参考:https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
PHP 的运行特点是一请求对应一进(线)程。服务器可以处理的 PHP 请求并发数受限于运行的 PHP 进(线)程总数。当一个请求结束,对应的 PHP 进(线)程也会退出(休眠),该请求中生成的上下文环境全部销毁。所以 PHP 最大缺陷就是每次请求都要重复获取配置信息,初始化程序环境。虽然也有以服务形式运行的 PHP 框架,如 Swoole 和 Workerman,但并不常见于生产环境。
Python Web 的部署方式
Python Web 程序有如下几种运行方式:
- WSGI
- uWSGI
- CGI
- SCGI
- FastCGI
- Apache Mod
其中以 WSGI 和 uWSGI 两种方式最为常见。主流 HTTP Server 软件,如 Apache、Nginx 和 Lighttpd,都支持 WSGI 协议;此外还有 Gunicorn、Tornado、Gevent、Twisted Web、bjoern、Meinheld 等也可以作为 WSGI 容器,独立运行 Python Web 程序并提供 HTTP 访问接口。uwsgi 是实现 uWSGI 协议的容器,目前主流 HTTP Server 也都支持 uWSGI 协议。普遍认为,uwsgi 的性能要高于常见的 WSGI 部署方式。
Nginx + uWSGI 方式配置参考:http://uwsgi-docs.readthedocs.org/en/latest/Nginx.html
不同于 PHP,常见的 Python Web 框架都是以服务的方式运行的。Python 程序长时间运行可能会发生各种异常,所以一些容器支持设定处理若干个请求后自动重启 Python 进程。
语言对比
内建数据类型比较
PHP | Python | 说明 |
---|---|---|
boolean | boolean | 布尔类型 |
int | int [1] | 整型 |
float | float | 浮点型 |
- | long [2] | 长整型 |
- | fractions | 分数 |
- | complex | 复数 |
- | byte | 字节 |
string | string [3] | 字符串 |
- | tuple | 元组 |
- | set | 集合 |
- | bytearray | 字节数组 |
array [4] | list | 列表 |
array | dict | 散列表(数组/字典) [5] |
object | object | 对象 |
null | NoneType | 空类型 |
resource | - | 资源 |
callable [6] | function | 函数/闭包/Lambda表达式 |
- Python 3.x 的 int 类型和 PHP 一样,最大值取决于系统平台; Python 2.x 的 int 类型为 32 位的。
- long 是 Python 2.x 的内置类型,Python 3.x 取消了该类型。
- Python 2.x 字符串分为 str 和 unicode 两种类型;Python 3.x 字符串皆为 unicode 类型。
- PHP 可以通过 array 类型来实现大部分列表的操作,虽然在实现方式上有很大的不同。
- PHP 的 array 是有序字典;Python的 dict 是无序字典,如果需要用到有序字典,可以使用 OrderedDict 类。
- PHP 5.4 之后引入 callable 类型。该类型可以是函数名称(字符串)、对象方法(数组)或者闭包(\Closure 对象)。
代码组织
PHP 以文件方式组织代码,语言本身对于文件目录结构没有任何要求。通过 require
或 include
语句来引用其他文件中的代码,或者使用 __autoload
来自动加载源代码文件。PSR-0 和 PSR-4 定义了 PHP autoload 的规范。
phprequire __DIR__ . '/lib/import.php';
$obj = new ClassNotLoaded();
function __autoload($class) {
// $name = 'ClassNotLoaded';
require __DIR__ . "/lib/{$class}.php";
}
Python 是由 Package 和 Module 的方式来组织的。一个包含 __init__.py
文件的文件夹可以作为一个 Package,里面的文件可以是 Module。通过 import
或 from ... import ...
语句来引用其他文件中的代码,还可以使用 __import__()
实现动态加载。Python 会从 sys.path
列表中保存的路径下去查找导入的包文件夹。
pythonimport sys
sys.path.append(my_lib_path)
from package_name import module_name
Python 2.7 开始,默认为绝对导入。之前版本需要开启。
pythonfrom __future__ import absolute_import
如果要进行相对导入,需要显示声明。
pythonfrom .package import module
from ..package import module
函数方法速查
字符串操作
PHP | Python | 说明 |
---|---|---|
$string = $str1 . $str2; | string = str1 + str2 | 字符串拼接 |
“My name is {$name}”; | “My name is %(name)s” % {“name”: name} “My name is %s” % (name) “My name is {name}".format(name=name) | 字符串格式化 |
ucfirst($string); | string.capitalize() | 首字母大写 |
trim($string); | string.strip() | 去除首尾空白字符 |
strtolower($string); | string.lower() | 转换为小写字符 |
strtoupper($string); | string.upper() | 转换为大写字符 |
substr($string, $i, $j - $i); | string[i:j] | 获取字符串子串 |
explode(”,", “1,2,3,4”); | “1,2,3,4”.split(",") | 展开字符串为数组/列表 |
implode(",", [1, 2, 3, 4]); | “,".join(map(str, [1, 2, 3, 4])) | 合并数组/列表为字符串 |
false !== strpos(‘php’, ‘h’); | ’t’ in ‘python’ | 查找字符串是否包含子串 |
strlen($string); | len(string) | 字符串长度 |
数组/列表操作
PHP | Python | 说明 |
---|---|---|
$array[] = $item; | array.append(item) | 向数组/列表末尾添加元素 |
array_push($array, $item1, $item2); | array.extend([item1, item2]) | 向数组末尾添加多个元素 |
array_splice($array, $pos, 0, $item); | array.insert(pos, item) | 指定位置插入元素 |
array_unshift($array, $item); | array.insert(0, item) | 向数组/列表头部插入元素 |
$item = array_pop($array); | item = array.pop() | 模拟栈,将末尾元素出栈 |
array_splice($array, $pos, 1); | del array[pos] | 删除数组/列表的元素 |
$array = $array1 + $array2; | array = array1 + array2 | 数组/列表相加 |
array_search($item, $array); | array.index(item) | 查找元素所在位置 |
count($array); | len(array) | 获取数组/列表长度 |
array_count_values($array)[item]; | array.count(item) | 统计元素在数组/列表里出现次数 |
array_slice($array, $i, $j); | array[i:j] | 切片操作 |
min($array); max($array); | min(array) max(array) | 求元素最小/大值 |
in_array($item, $array); | item in array | 元素是否存在 |
sort($array); | array.sort() | 排序 |
数组/字典操作
PHP | Python | 说明 |
---|---|---|
unset($array[$key]); | del array[key] | 删除键值对 |
array_key_exists($key, $array); isset($array[$key]); | key in array array.has_key(key) | 键名是否存在 |
array_values($array); | array.values() | 获取全部值组成的数组/列表 |
array_keys($array); | array.keys() | 获取全部键名组成的数组/列表 |
array_merge($array1, $array2); | dict(array1, **array2) | 合并两个数组/字典 |
array_combine($keys, $values); | dict(zip(keys, values)) | 用两个数组/列表分别作为数组/字典的键名和值 |
PHP 数组遍历
$array = [1, 2, 3, 4];
for ($i = 0; $i < count($array); $i++) {
echo 'key:', $i, '; ';
echo 'value:', $array[$i], PHP_EOL;
}
$array = [1, 2, 3, 'k1' => 'v1', 'k2' => 'v2'];
foreach ($array as $key => $value) {
echo 'key:', $key, '; ';
echo 'value:', $value, PHP_EOL;
}
foreach ($array as $item) {
echo 'value:', $item, PHP_EOL;
}
Python list/dict 遍历
array = [1, 2, 3, 4]
for item in array:
print('value: %i' % (item))
for index, value in enumerate(array):
print('index: %i; value: %i' % (index, value))
array = {'k1': 'v1', 'k2': 'v2'}
for key in array:
print('key: %s; value: %s' %(key, array[key]))
for key, value in array.items():
print('key: %s; value: %s' %(key, value))
for key, value in array.iteritems():
print('key: %s; value: %s' %(key, value))
.items()
和 .iteritems()
区别在于前者返回一个列表,后者返回一个可迭代对象,更加节省内存。在 Python 3 里,.items()
也返回一个可迭代对象,取消了 .iteritems()
方法。
Python 内建函数
PHP | Python | 说明 |
---|---|---|
abs() | abs() | 绝对值 |
- | all() | 所有值为 true/True |
- | any() | 存在任意值为 true/True |
- | basestring() | unicode字符串和普通字符串的基类 |
decbin() | bin() | 将整数转换成二进制字面表示 |
boolval() | bool() | 生成一个布尔类型对象 |
- | bytearray() | |
is_callable() | callale() | 是否是可调用对象 |
chr() | chr() | 返回 ASCII 字符 |
- | classmethod() | |
- | cmp() | |
- | compile() | |
- | complex() | |
- | delattr() | |
array() | dict() | 生成一个数组/字典类型对象 |
- | dir() | |
- | divmod() | |
- | enumerate() | |
eval() | eval() | |
require include | execfile() | 执行文件内的代码 |
new SplFileObject() | file() | 创建一个文件类型对象 |
array_filter() | filter() | 过滤数组/可迭代对象 |
floatval() | float() | 生成一个浮点类型的对象 |
- | format() | |
- | frozenset() | |
$object->$attr_name | getattr() | |
$GLOBALS | globals() | 返回所有全局变量 |
method_exists() property_exists() | hasattr() | |
- | help() | |
dechex() | hex() | 将整数转换成十六进制字面表示 |
spl_object_hash() | id() | 返回对象的唯一 id |
- | input() | |
intval() | int() | 生成一个整型对象 |
instanceof is_a() | isinstance() | 判断对象是否为某个类的实例 |
is_subclass_of() | issubclass() | 判断类是否是某个类的子类 |
SPL Iterators | iter() | 将可迭代对象转换成一个迭代器 |
iterator_count() count() strlen() | len() | 返回数组/迭代对象/字符串的长度(元素个数) |
array() | list() | 生成一个数组/列表对象 |
get_defined_vars() | locals() | 获取所有本地变量 |
intval() | long() | 生成一个长整型对象 |
array_map() iterator_apply() | map() | 遍历数组/可迭代对象的元素生成新的对象 |
max() | max() | 获取最大值 |
- | memoryview() | |
min() | min() | 获取最小值 |
next() | next() | 获取可迭代对象的下一个元素 |
- | object() | |
decoct() | oct() | 将数字转换成十进制字面表示 |
fopen() | open() | 打开文件 |
ord() | ord() | 返回字符的 ASCII 码 |
pow() | pow() | 求指数 |
echo print() | print() | 输出 |
- | property() | |
range() | range() | 返回一个指定范围的数组/列表 |
- | raw_input() | |
array_reduce() | reduce() | 迭代计算数组/可迭代对象 |
- | reload() | |
var_export() | repr() | 输出一个可打印的对象 |
var_dump() | pprint.pprint() | 格式化输出对象 |
array_reverse() | reversed() | 倒序排列数组/可迭代对象 |
round() | round() | 对浮点数四舍五入 |
- | set() | |
$object->$attr_name = $value | setattr() | 设置对象的属性值 |
- | slice() | |
usort() | sorted() | 对数组/列表/可迭代对象排序 |
- | staticmethod() | |
- | str() | |
array_sum() | sum() | 计算元素数值的总和 |
parent get_parent_class() | super() | 获取父类或父类对象 |
- | tuple() | |
gettype() | type() | 获取对象类型 |
- | unichr() | |
- | unicode() | |
get_object_vars() get_class_vars() | vars() | 获取对象/类的成员属性和值 |
- | xrange() | |
- | zip() | |
require include | __import__() | 动态载入模块/代码文件 |
文件操作函数
PHP | Python | 说明 |
---|---|---|
file_exists() | os.path.exists() | 判断文件是否存在 |
is_file() | os.path.isfile() | 判断是否是文件 |
is_dir() | os.path.isdir() | 判断是否是目录 |
is_link() | os.path.islink() | 判断是否是链接 |
basename() | os.path.basename() | 获取文件名称 |
dirname() | os.path.dirname() | 获取文件路径 |
filesize() | os.path.getsize() | 获取文件大小 |
fileatime() | os.path.getatime() | 获取文件访问时间 |
filemtime() | os.path.getmtime() | 获取文件修改时间 |
filectime() | os.path.getctime() | 获取文件创建时间 |
realpath() | os.path.realpath() | 获取真实路径 |