Rumah > Artikel > pembangunan bahagian belakang > Artikel panjang 10,000 perkataan, penjelasan pemformatan rentetan Python
Helo semua, saya seorang pemula!
Hidup ini singkat, saya belajar Python!
Artikel hari ini sangat terperinci dan boleh dipanggil penjelasan paling lengkap tentang output berformat rentetan dalam sejarah!
Apabila saya melihat "pemformatan data panda" hujung minggu lalu, saya ingin meringkaskan mata pengetahuan ini (menetapkan tempat perpuluhan, menetapkan persentil, menetapkan ribuan pemisah). Walau bagaimanapun, saya terus mengetahui lebih banyak lagi, dan semuanya tidak dapat dipisahkan daripada pemformatan rentetan, jadi saya berpaling dan menyemak pengetahuan pemformatan rentetan.
Tetapi saya tidak pernah menjangkakannya, saya fikir tidak ada banyak titik pengetahuan, tetapi setelah menyusunnya dengan teliti, saya masih mengambil masa lebih dari seminggu untuk memahami kebanyakannya, terutamanya g dan Berkenaan dengan penggunaan G. , Baidu dan Google adalah terlalu umum Kemudian saya pergi ke laman web rasmi untuk membacanya, tetapi laman web rasmi saya benar-benar tidak dapat memahami beberapa maksud, jadi saya mula menggiling dan mencubanya sedikit demi sedikit , mungkin lebih baik untuk memikirkannya sembilan kali daripada sepuluh, jadi siaran yang anda lihat di bawah terbentuk...
1. Sintaks
"%[(name)][flags][width][.precison]type" % 待格式化数据
2 . "kekalkan perpuluhan kepada n tempat selepas titik perpuluhan" atau "kekalkan n digit bererti", anda perlu membuat pembundaran nombor yang sesuai Sebagai contoh, jika anda perlu membundarkan 1.125 kepada dua tempat perpuluhan, hasilnya ialah 1.13. . Walau bagaimanapun, jika anda menggunakan % atau pemformatan format, hasil yang anda peroleh adalah sangat serupa dengan apa yang anda jangkakan, seperti berikut:
(1) %: 占位符; (2) (name):命名占位字符; (3) flags可选: 1) +: 右对齐,正数加正号,负数加负号; 2) -: 左对齐,正数无符号,负数加负号; 3) 空格: 右对齐(默认的对齐方式),正数前加空格,负数前加负号; 4) 0: 右对齐,以0填充,正数无符号,负数加负号,并将符号放置在0最左侧; (4) width: 占位宽度, 若指定宽度小于原数据长度则按原长度数据输出; (5) .precison: 小数点后保留位数;在字符串中则表示截取/字符串切片; (6) type: 详见如下...
Seperti yang anda boleh lihat daripada keputusan di atas, simpan 1.125 dalam dua digit Perpuluhan keputusan ialah 1.12, bukan 1.13 Mengapa ini? Sila teruskan membaca (dibundarkan kepada lima pasang)...
(1) s: string, 字符串; (2) d: decimal integer, 十进制数; (3) i: integer, 用法同%d; (4) u: unsigned integer, 无符号十进制数; (5) f: float, 浮点数(默认保留小数点后6位); (6) F: Float, 浮点数(默认保留小数点后6位); (7) e: exponent, 将数字表示为科学计数法(小写e, 默认保留小数点后6位); (8) E: Exponent, 将数字表示为科学计数法(大写E, 默认保留小数点后6位); (9) o: octal, 八进制数(即0-7); (10) x: hexdecimal, 十六进制数(即0-9a-f); (11) X: Hexdecimal, 十六进进制数(0-9A-F); (12) g: general format, 通用格式,详见如下...; (13) G: General format, 通用格式,详见如下...; (14) %c: character, 将十进制数转换为所对应的unicode值; (15) %r: representation, 调用__repr__魔法方法输出; (16) %%: 转义%,输出百分号。
Dibundarkan kepada lima pasangan
print("{:.2f}".format(1.125)) >>> 1.12 print("%.2f" % 1.125) >>> 1.12
Jika terdapat sebarang nombor yang bukan 0 selepas digit n+1, maka digit ke-n dibundarkan dengan 1 sama ada nombor ganjil atau nombor genap.
a. >
b. Tukar nombor titik terapung perpuluhan kepada perduaan: pendaraban asas dan pembundaranMantissa tidak tepat Bahagian perpuluhan terapung; nombor mata ditukar kepada binari Mungkin terdapat situasi di mana perpuluhan tak terhingga tidak boleh didarab. Walau bagaimanapun, komputer tidak boleh mengendalikan perpuluhan tak terhingga Ia akan mengekalkan sehingga 53 digit dalam nombor perduaan yang sepadan dengan nombor titik terapung perpuluhan, dan data selepas 53 digit akan dipotong terus, mengakibatkan ketidaktepatan apabila menukar nombor titik terapung binari kembali. kepada perpuluhan.
;
如果只定义了__str__ 或__repr__中的一个,那么print(cat)都将输出其对应的返回值,类似返回"我是小黑"或"我的名字是小黑";
如果既定义了__str__和__repr__两个魔法方法,那么print(cat)将输出__str__对应的返回值;__repr__和__str__的区别在于,一个侧重用户,一个侧重开发人员。如果定义了__repr__方法,那么在一些编辑器(Jupyter Notebook, JypyterLab)或终端中直接传递对象名即可获取__repr__的返回值,如下图所示:
5.用法详解
(1). name
(1.1) 不指定name 1) 单个数据 print("|我是%s" % "王暖暖|") >>> |我是王暖暖| 2) 多个数据: 使用元组 print("|我是%s,今年%d岁|" % ("王暖暖", 18)) >>> |我是王暖暖,今年18岁| (1.2) 指定name: 使用字典 1) 单个数据 print("|我是%(name)s|" % {"name": "王暖暖"}) >>> |我是王暖暖| 2) 多个数据 print("|我叫%(name)s, 今年%(age)d岁。|" % {"name": "王暖暖", "age": 18}) >>> |我叫王暖暖, 今年18岁。| (1.3) 单个数据对应多个占位 # 元组内元素数量必须和占位符数量统一 print("|我是 %s %s %s!!!|" % ("王暖暖", "王暖暖", "王暖暖")) # 使用字典则必须指明键值对 print("|我是 %(name)s %(name)s %(name)s!!!|" % ({"name": "王暖暖"})) >>> |我是王暖暖 王暖暖 王暖暖!!!|
(2). flags + width
# 依次按flags中"+", "-", " ", "0"结合width=10演示 (2.1) 字符串: print("|%+10s|" % "王暖暖") >>> | 王暖暖| # 字符串右对齐 print("|%-10s|" % "王暖暖") >>> |王暖暖 | # 字符串左对齐 print("|% 10s|" % "王暖暖") >>> | 王暖暖| # 字符串右对齐 print("|%010s|" % "王暖暖") >>> | 王暖暖| # 字符串右对齐 (2.2) 正整数 print("|%+10d|" % 26) >>> | +26| # 正整数右对齐,正数加正号 print("|%-10d|" % 26) >>> |26| # 正整数左对齐,正数无符号 print("|% 10d|" % 26) >>> |26| # 正整数右对齐,正数前加空格 print("|%010d|" % 26) >>> |0000000026| # 正整数右对齐,正数无符号,以0填充 (2.3) 负整数 print("|%+10d|" % -26) >>> | -26| # 负整数右对齐,负数加负号 print("|%-10d|" % -26) >>> |-26 | # 负整数左对齐,负数加负号 print("|% 10d|" % -26) >>> | -26| # 负整数右对齐,负数加负号 print("|%010d|" % -26) >>> |-000000026| # 负整数右对齐,负数加负号, 符号和数字之前填充0 (2.4) 正浮点数 # 如未指定浮点数精度,默认保留6位小数,其余均用空格填充(如指定0则用0填充);若width小于浮点数的数位则width无效。 print("|%+10f|" % 2.2) >>> | +2.200000| # 正浮点数加正号右对齐,小数部分以0填充 print("|%-10f|" % 2.2) >>> |2.200000| # 正浮点数左对齐,小数点后为空格 print("|% 10f|" % 2.2) >>> |2.200000| # 正浮点数右对齐,浮点数前为空格 print("|%010f|" % 2.2) >>> |002.200000| # 正浮点数右对齐,小数点前以0填充 (2.5) 负浮点数 print("|%+10f|" % -2.2) >>> | -2.200000| # 负浮点数加负号右对齐,小数部分以0填充 print("|%-10f|" % -2.2) >>> |-2.200000 | # 负浮点数加负号左对齐,小数点后为空格 print("|% 10f|" % -2.2) >>> | -2.200000| # 负浮点数加负号右对齐,其余用空格填充 print("|%010f|" % -2.2) >>> |-02.200000| # 负浮点数加负号右对齐,其余用0填充,注意符号在最左侧 (2.6) 详详解 1) print("|%+15f|" % 22.6) >>> | +22.600000| a) 未指定保留位数,故小数点后占6位,用0填充; b) 小数点占1位,"+"号占1位,共2位; c) 小数点前系数"22"占2位; c) 其余均用空格填充,故空格占5位,总计15位. 2) print("|%+015f|" % 22.6) >>> |+0000022.600000| a) 未指定保留位数,故小数点后占6位,用0填充; b) 小数点占1位,"+"号占1位,共2位; c) 小数点前系数22占2位; d) 其余均用0填充,故小数点前的"0"占5位,总计15位; e) 注意: 此处同时使用了"+"和"0",配合二者的功能使用。 3) print("|%+15.3f|" % 22.66) >>> |+22.660| a) 指定保留小数位数为3位,不足的用0填充; b) 其余的用空格填充; 4) print("|%+015.3f|" % 22.66) >>> |+0000000022.660| a) 指定保留小数位数为3位,不足的用0填充; b) 其余的用"0"填充;
(3). precision
(3.1) 字符串 如果待格式化数据为字符串则表示字符串截取 print("|%.2s|" % "python") >>> |py| (3.2) 浮点数 保留小数点后.precision数字 print("|%(num).2f|" % {"num": 0.145}) >>> |0.14| print("|%(num).2f|" % {"num": 1.145}) >>> |1.15| print("|%(num).2f|" % {"num": 2.145}) >>> |2.15| print("|%(num).2f|" % {"num": 3.145}) >>> |3.15| 注意: 此处列举的数字均存在"不精确尾数"和"四舍六入五双"两种情况 (3.3) 科学计数 print("|%.3f用科学计数法表示写作%.2E|" % (40.125, 40.125)) >>> |40.125用科学计数法表示写作4.01E+01| 解析: 先将40.125转为科学计数法形式: 4.0125*10^1(4.0125乘以10的1次方); 而后再对4.0125精确到小数点后位, 即4.01; 最后用e或E分隔系数和指数,即为4.01E+01 (3.4) g/G模式: 详见如下...
(4). type
(1) s: 字符串 print("|我是%s|" % "王暖暖") >>> |我是王暖暖| (2) d, i, u: 十进制数字 print("|我最喜欢的十进制数是%d|" % 26) print("|我最喜欢的十进制数是%i|" % 26) print("|我最喜欢的十进制数是%u|" % 26) >>> |我最喜欢的十进制数是26| (3) f: 浮点数(默认保留6位小数) # 保留小数详情见上... print("|这是一个浮点数%f|" % 2.26) >>> |这是一个浮点数2.260000| (4) e, E: 科学计数 print("|%f用科学计数法表示写作%e|" % (4.145, 4.145)) >>> |4.145000用科学计数法表示写作4.145000e+00| print("|%.3f用科学计数法表示写作%.2E|" % (4.145, 4.145)) >>> |4.145用科学计数法表示写作4.14E+00| (2) o: 八进制 print("|十进制%(num)d对应的八进制数为%(num)o|" % {"num": 26}) >>> |十进制26对应的八进制数为32| (3) x, X: 十六进制 print("|十进制%(num)d对应的十六进制数为%(num)x|" % {"num": 26}) >>> |十进制26对应的十六进制数为1a| print("|十进制%(num)d对应的十六进制数为%(num)X|" % {"num": 26}) >>> |十进制26对应的十六进制数为1A| (6) g, G详见如下... (7) c: unicode字符 print("|%d对应的unicode字符为:%c|" % (226, 226)) >>> |226对应的unicode字符为:â| (12) %r: representation, 调用传入对象的__repr__方法的返回值 经测试,无论是使用%s类型还是%r类型,使用JypyterLab均直接输出格式化结果,其二者的却别在于,使用%r模式会在字符串数据的左右两侧加上'', 详见下图... (11) %%: 转义%。 如果有待格式化数据需要输出百分号(%),需要使用%%进行转义 print("|I'm %d%% sure.|" % 100) >>> |I'm 100% sure.|
1.语法
"{[index][:[[fill]align][sign][#][0][width][grouping_option][.precision][type]]}".format()
2.参数详解
(1) index: 待格式化字符的索引或键,若占位符数量和参数数量不一致时必须指定索引; (2) fill: 填充字符,可为任意字符; (3) align: 对齐方式(常配合width使用),可选: # 和Excel中输入文本和数字的默认对齐方式一致 1) <: 左对齐(字符串默认对齐方式); 2) >: 右对齐(数字默认对齐方式); 3) ^: 居中对齐; 4) =: 内容右对齐,将符号(+或-)放置在填充字符的左侧,仅对数字类型有效; (4) sign: 有无符号,可选: 1) +: 正数加正号,负数加负号; 2) -: 正数不变,负数加负号(默认); 3) 空格: 正数加空格,负数加负号; (5) #: a. 对于整数,在输出值分别添加响应的0b, 0o, 0x前缀; b. 对于浮点数和复数, 在输出值保留小数点符号; c. 在g/G模式下,保留末尾的0; (6) 0: 若未设置对齐方式,在width前加一个0将为数字类型启用感知正负号的零填充,等同于设置fill为0, align为"="; (7) width: 字段总宽度(十进制整数), 所有前缀,分隔符和其它格式化字符之和; (8) grouping_option: 设置分组(分隔): 1) ",": 使用逗号作为千位分隔符; 2) "_": 使用_作为分隔符: a. 对于十进制数, 使用_作为千位分隔符; b. 对于b, o, x/X,使用_每4位数插入一个下划线; (9) .precision(十进制数): a. 整数型不允许设置precison, 如果设置即被转换为浮点数; b. 浮点型表示小数点"后"显示多少位小数位数; c. 以g或G格式化表示在小数点"前后"共显示多少个数位; d. 字符型表示截取多少个字符; (10) {{或}}: 转义{或},当需要输出{或}的使用使用; (11) type: 详见如下...
3.type:
format()格式化与%格式化的type大同小异,以下尽挑重点讲解 (1) b: binary, 二进制; (3) g: general formatting, 详见如下... (4) G: General formatting, 详见如下...
4.genaral formatting
g和G模式是我花时间最多去琢磨的一个点,所以单独把它抽离出来讲解。这里的g字母是general的缩写,百度可以查到一些资料,说某种条件下, g模式等同于f模式或e模式。但是,实际上,g与f, e这两种模式还有一些区别,详见如下:
(1) 给定精度 对于给定精度 p >= 1,会将数值舍入到p个有效数位,再将结果以小数或科学计数法进行格式化,精度0会被视为等价于精度1。 1) 对于浮点数: print("|{:.2G}|".format(3.125)) 先将3.125转换为科学计数法表示,即为3.125*10^0; 此时,指定的精度p=2, 表示小数点前后共保留2个有效数位, 指数exp=0,则 如果-4 ≤ exp < p(-4 ≤ 0 < 2),该数将使用"f"模式和精度p-1-exp(2-1-0=1)格式化,故 结果为: |3.1| 2) 对于Decimal: print("|{:.2G}|".format(Decimal("4.145"))) 先将Decimal("4.145")转换为科学计数法表示,即为4.145*10^0; 此时,指定的精度p=2, 表示小数点前后共保留2个有效数位,指数exp=0, 则 如果-6 ≤ exp < p(-6 ≤ 0 < 2), 该数将使用"f"模式和精度p-1-exp(2-1-0)格式化,故 结果为: |4.1| 3) 如果不满足m ≤ exp < p(m=-4或-6), 则使用"e"模式和精度p-1表示: print("|{:.3G}|".format(4225.125)) 先将4225.125转换为科学计数法表示,即为4.225125*10^3; 此时,指定的精度p=3, exp=3, 则 -4 ≤ exp < p(-4 ≤ 3 < 3)不成立,所以使用"e"模式和精度p-1(3-1=2)表示,故 结果为: |4.23E+03| print("|{:.3G}|".format(Decimal("4225.256"))) 同理如上,结果为|4.23E+3| (2) 未给定精度 如未指定精度,会对浮点数采用6个有效数位的精度; 对于 Decimal,结果的系数会沿用原值的系数数位。 只有很小的数字或很大的数字才会使用"e"模式表示, 其余的均用"f"模式表示: a. 绝对值小于等于1e-6(0.000001)的数使用"e"模式表示; b. 小数点前的数位大于6的数使用"e"模式表示。 例如: print("|{:G}|".format(0.0000002)) >>> |2E-07| print("|{:G}|".format(5555555.6666)) >>> |5.55556E+06| (3) 注意点 1) 需要注意的是,g/G和f,e/E并不完全相同,主要体现在精度的处理上。 对于f而言,精度p指的是保留小数点后p位小数; 对于e而言,精度p指的是将数据转换为科学计数法后保留小数点后p位; 而g/G模式下,则表示小数点前后保留p位有效数字。 print("|{:.3G}|".format(5555.6666)) >>> |5.56E+03| print("|{:.3E}|".format(5555.6666)) >>> |5.556E+03| print("|{:.3f}|".format(5555.6666)) >>> |5555.667| 2) 如果小数点之后没有数位,则小数点也会被略去,除非使用了#选项 print("{:G}".format(333.0)) >>> 333 print("{:#G}".format(333.0)) >>> 333.000 print("{:f}".format(333.0)) >>> 333.000000 print("{:E}".format(333.0)) >>> 3.330000E+02
5.用法详解
基于前文已经详细讲解了%格式化中各个参数的用法,此处便不再做过多赘述,更多以实例讲解,如有必要再做具体解析。
(1). index
print("|我叫{}, 今年{}岁.|".format("Zack", 18)) # 不指定index print("|我叫{0}, 今年{1}岁.|".format("Zack", 18)) # 数字 print("|我叫{0[0]}, 今年{0[1]}岁.|".format(("Zack", 18, ))) # 元组 print("|我叫{name}, 今年{age}岁.|".format(name="Zack", age=18)) # 关键字参数 info = {"name": "Zack", "age": 18} print("|我叫{name}, 今年{age}岁.|".format(**info)) # 字典 >>> |我叫Zack, 今年18岁。| print("|该复数的实部为{0.real}, 虚部为{0.imag}|".format(1+2j)) >>> |该复数的实部为1.0, 虚部为2.0|
(2). fill+width+align
fill = & align = None width = 10 (1) 不指定align,无法指定fill, 默认为空格 print("|{0:10}|".format("王暖暖")) >>> |王暖暖 | # 字符串 print("|{0:10}|".format(226)) >>> | 226| # 数字 (2) 指定align, fill=&, width=10 print("|{0:&<10}|".format("王暖暖")) >>> |王暖暖&&&&&&&| print("|{0:&>10}|".format("王暖暖")) >>> |&&&&&&&王暖暖| print("|{0:&^10}|".format("王暖暖")) >>> |&&&王暖暖&&&&| print("|{0:&=10}|".format(-226)) >>> |-&&&&&&226|# 符号放置最左侧
(3). sign+align+fill+width
# 均以数字演示 sign=None align=None fill=* width=10 (1) "+": print("|{0:*<+10}|".format(226)) >>> |+226******| print("|{0:*>+10}|".format(-226)) >>> |******-226| (2) "-": print("|{0:*<-10}|".format(226)) >>> |226*******| print("|{0:*>-10}|".format(-226)) >>> |******-226| (3) " ": print("|{0:*< 10}|".format(226)) >>> |*** 226***| # 整数前有空格 print("|{0:*< 10}|".format(-226)) >>> |***-226***| # 负数前有负号
(4). g/G
(1) b, o, x/X print("|{0:#b}|".format(226)) >>> |0b11100010| print("|{0:#o}|".format(226)) >>> |0o342| print("|{0:#X}|".format(226)) >>> |0XE2| (2) 浮点数和复数 即使指定小数点后保留0位数字,依旧保留小数点 print("|{:.0f}|".format(3.14)) >>> |3| print("|{:#.0f}|".format(3.14)) >>> |3.| print("|{:.0f}|".format(1+2J)) >>> |1+2j| print("|{:#.0f}|".format(1+2J)) >>> |1.+2.j| (3) g/G: print("{:G}".format(333.0)) >>> 333 print("{:#G}".format(333.0)) >>> 333.000
(5). "0"
(1)若未设置对齐方式,在width前加一个0将为数字类型启用感知正负号的零填充,等同于设置fill为0, align为"=" print("|{0:010}|".format(-3.14)) >>> |-000003.14| 等同于 print("|{0:0=10}|".format(-3.14)) >>> |-000003.14| 注意区别于 print("|{0:0>10}|".format(-3.14)) >>> |00000-3.14| 此功能等同于%格式化中的"0", 如下所示: print("|%010.2f|" % -3.14) >>> |-000003.14|
(6). group_options
(1) ","千位分隔符 print("|{0:,}|".format(3141.5926)) >>> |3,141.5926| (2) "_" 1) 对于十进制数,使用"_"作为千位分隔符 print("|{0:_}|".format(3141.5926)) >>> |3_141.5926| 2) 对于b, o, x/X,使用"_"每四位插入一个下划线 print("|{0:_b}|".format(12345)) >>> |11_0000_0011_1001| print("|{0:_o}|".format(12345)) >>> |3_0071|
(7). {{或}}转义
print("This is a set: {{{0}}}".format("1, 2, 3")) >>> This is a set: {1, 2, 3}
(8). 补充
在处理精密数据的时候,因为不精确尾数的关系,可能导致一些数据失信,如下所示,将数据保留两位小数,有的精确为0.14而有的却精确为0.15。虽然Decimal可以处理此类问题,但是经过测试,Decimal并不使用于%格式化。传入Decimal和直接传入浮点数的结果一致,并无任何区别。故,如果要处理此类问题还是需要使用str.format()形式并传递Decimal类型的数据。
print("|%.2f|" % 0.145) >>> |0.14| print("|%.2f|" % Decimal("0.145")) >>> |0.14| print("|%.2f|" % 1.145) >>> |1.15| print("|%.2f|" % Decimal("1.145")) >>> |1.15| print("|{:.2f}|".format(Decimal("0.145"))) >>> |0.14| print("|{:.2f}|".format(Decimal("1.145"))) >>> |1.14|
1.语法
python3.6以后开始支持f-string字符串。f-string即formatting string, 它是str.format()的一个变种,其语法形式之殊途同归,很多时候使用f-string可以有效减少代码量,更为清晰易懂。语法:f"{}{}{}"
2.示例
(1) name = "Zack" age = 18 print(f"|我是{name}, 今年{age}岁|") >>> |我是Zack, 今年18岁| (2) for p in range(3): url = f"https://www.baidu.com/s?wd=python&pn={p*10}&oq=python" (3) 可直接调用对应对象的方法和属性 channel = "ted" print(f"|我喜欢观看{channel.upper()}学习英语|")
1.语法
# x为需要格式化的数据,formatter为格式化表达式,不需要指定{}。 format(x, formatter)
2.示例
#序列号 nums = [1, 2, 3] serial_nums = [format(x, "0>8") for x in nums] print(serial_nums) >>> ['00000001', '00000002', '00000003']
python字符串格式化语法较多,不便记忆,可以在具体需要使用的时候再查询即可。%格式化可以满足大多常用的功能,但是处理一些精密化或复杂的格式化需求的时候就束手无策了,所以推荐使用str.format()或f-string格式化处理字符串。
f-string是str.format()的一个分之,在一些特定情况下使用可以大大减少代码量,使代码更加清晰易懂,可以有选择性的使用f-string。
format()是python的一个内置函数,其使用频率不高,语法和str.format()大同小异,可以结合lambda函数使用或在其它一些特定情况下使用。
字符串格式化就讲到这里,我们下次再见啦~ bye bye
为什么浮点数在计算机中可能不精确?https://mp.weixin.qq.com/s/3pg1wtsOnFqvmSw13YPVPg
如何在python里面精确四舍五入 https://mp.weixin.qq.com/s/25NMrQtFHUq0A4e4VpzT6Qpython
字符串格式化
https://www.php.cn/link/398410ece9d7343091093a2a7f8ee381
python官网
https://www.php.cn/link/4d215ab7508a3e089af43fb605dd27d1
Atas ialah kandungan terperinci Artikel panjang 10,000 perkataan, penjelasan pemformatan rentetan Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!