The difference between PHP and Python is summarized as a memorandum from the perspective of PHP.
Anyway, Python is short and easy to write. The same result is output even if converted as follows. There is no choice but to get used to this culture rather than learning it.
Before conversion
def test(v):
r = []
if v > 0:
for i in range(v):
r += [v - i]
return r
After conversion
test = lambda v: [v - i for i in range(v)] if v > 0 else []
There is also code golf, and there is a competition to write a short code (see here for details).
In Python3, you can use a function called Interactive Mode, and if you enter a single line of code, the content will be evaluated and executed. Will be done. If there is an error, it will be pointed out on the spot, which is convenient for simple operation check and calculation.
An array that was used as a matter of course in PHP. Python3 also has similar functions such as lists, tuples, dictionaries, and sets, but it is necessary to use them properly depending on the purpose of use. Except for sets, you can specify not only objects but also lists, tuples, dictionaries, and sets as elements like PHP.
A simple array like $ a = [1, 2, 3];
in PHP can also be represented in Python 3 with ʻa = [1, 2, 3]. Multidimensional is also possible. Each element can be obtained by setting ʻi, j, k = a
.
However, it is necessary to use a dictionary to realize a function like a reference array like PHP.
PHP has ʻarray_slice, but Python 3 has more useful features. By setting ʻa = b [m: n]
, the n-1
th element from the m
th can be cut out. If m
is omitted, it will be from the beginning, and if n
is omitted, it will be to the end. If m
and n
are negative, they can be specified in reverse. Also, there is a ʻa = b [:: m]extended slice, which can be obtained every
m`.
a = [0, 1, 2, 3, 4, 5, 6, 7]
print(a[2:5])
print(a[4:])
print(a[:4])
print(a[-1:-4])
print(a[-1:])
print(a[:-4])
print(a[::3])
print(a[::-1])
Output result
[2, 3, 4]
[4, 5, 6, 7]
[0, 1, 2, 3]
[4, 5, 6]
[4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6]
[0, 3, 6]
[7, 6, 5, 4, 3, 2, 1, 0]
If you set ʻa [1: 6: 3]`, you can cut out from the 1st to the 5th, and take out every 3 more.
When you get used to PHP, you are worried about the handling of character strings. In Python3, it can be made into an array as shown below, so character strings can be handled easily.
a = "abcd"
b1 = list(a)
b2 = [a[i:i+2] for i in range(0, len(a), 2)]
print(b1, b2)
Output result
['a', 'b', 'c', 'd'] ['ab', 'cd']
A list whose values cannot be changed, roughly speaking. It can be defined as ʻa = (1, 2, 3), and elements can be obtained like a list by setting ʻi, j, k = a
. In the case of PHP, if there are return values of multiple functions, it was necessary to bother to return in an array, but in the case of Python3, using this property, specify with tuples such as return r1, r2, r3
can do.
Something like a PHP reference array. It can be used when parsing JSON. For example, PHP description such as $ a = ['a' => 1,'b' => 2];
, in Python3, ʻa = {'a': 1,'b': 2} Can be expressed. Also, if ʻi, j = a
, you can get the key instead of the value. Even if b = list (a)
is set, the list of elements composed of the keys of ʻa is assigned to
b`.
When creating an array with unique elements in PHP, it was necessary to apply ʻarray_unique every time like
$ a = array_unique ([1, 1, 2, 3, 3, 3]); , By defining ʻa = {1, 2, 3}
in Python3, no duplication is guaranteed even if ʻa.add (1)` is used thereafter.
l1 = [1, 2, 3]
print(l1)
l2 = [4, 5, 6, l1]
print(l2)
print(11 + l2)
t1 = ("a", "b", "c")
print(t1)
t2 = ("d", l1, l2)
print(t2)
print(t1 + t2)
d1 = {'a':l1, 1:l2, "c":t1}
s1 = set(l1)
print(s1)
print({'d1':d1, 's1':s1})
Output result
[1, 2, 3]
[4, 5, 6, [1, 2, 3]]
[1, 2, 3, [4, 5, 6, [...]]]
('a', 'b', 'c')
('d', [1, 2, 3, [4, 5, 6, [...]]], [4, 5, 6, [1, 2, 3, [...]]])
('a', 'b', 'c', 'd', [1, 2, 3, [4, 5, 6, [...]]], [4, 5, 6, [1, 2, 3, [...]]])
{1, 3, 5}
{1, 3, 5}
{'d1': {1: [4, 5, 6, [1, 2, 3, [...]]], 'c': ('a', 'b', 'c'), 'a': [1, 2, 3, [4, 5, 6, [...]]]}, 's1': {1, 3, 5}}
Since it is abbreviated as ...
in the output result, the method to display without omitting it is here Will be helpful.
Python3 has the concept of immutable and mutable. It means that immutables cannot be changed, and mutables can be changed. The tuples mentioned above are immutable, and lists, dictionaries, and sets are mutable. This is the behavior of "assignment", which is very different between PHP and Python3. The behavior of this assignment in Python3 is similar to that in Ruby, and it is summarized in here.
In Python3, assignment means "make a binding between the target and the object". When you assign an object to a variable, you store a reference to the object in the variable. The following is an output example of the object ID (identification value) when an immutable object is assigned.
Manipulating the variable ʻa changes the ʻid
of ʻa, which is immutable because it cannot be changed for the integer object
3`. Here, for convenience, such an object is treated as an immutable object.
a = 3
print("id_3:%d, id_a:%d" % (id(3), id(a)))
b = a
print("id_b:%d" % id(b))
a += 1
print("id_3:%d, id_4:%d, id_a:%d, id_b:%d" % (id(3), id(4), id(a), id(b)))
Output result
id_3:1623654960, id_a:1623654960
id_b:1623654960
id_3:1623654960, id_4:1623654992, id_a:1623654992, id_b:1623654960
Even if the value is changed by manipulating ʻa, it is the same ʻid
and can be changed to a different value. That is, it is mutable (changeable). Here, for convenience, such an object is treated as a mutable object.
When the value of ʻa is assigned to
b, ʻid
is the same, so if the value is changed by manipulating ʻa,
b` also changes.
a = [1,2,3]
b = a
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
a[1] = 4
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
Output result
id_a:4332032456, id_b:4332032456
[1, 2, 3] [1, 2, 3]
id_a:4332032456, id_b:4332032456
[1, 4, 3] [1, 4, 3]
In the case of a mutable object, as in the above example, if the value of ʻa is assigned to
b, the ʻid
is the same, so if the value is changed by manipulating ʻa,
b Also changes. You need to make a copy to make the value of
b independent of ʻa
. In the case of the list or array in this example, it can be realized by making a shallow copy.
In the example below, by making a shallow copy, the value of b
does not change even if the value is changed by the operation of ʻa. A shallow copy can be made by substituting the
copy.copy function or ʻa [:]
.
import copy as cp
a = [1,2,3]
b = cp.copy(a)
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
a[1] = 4
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
b = a[:]
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
a[1] = 3
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
Output result
id_a:4460690760, id_b:4460690888
[1, 2, 3] [1, 2, 3]
id_a:4460690760, id_b:4460690888
[1, 4, 3] [1, 2, 3]
id_a:4460690760, id_b:4460691272
[1, 4, 3] [1, 4, 3]
id_a:4460690760, id_b:4460691272
[1, 3, 3] [1, 4, 3]
For example, in the following example where the element of the list is a list and the element of the array is an array, that is, there is another mutable object from the mutable object, even if you make a shallow copy, you can operate ʻa [0] . The value of
b [0]` is changed. This behaves the same for both Python 3.6 and Ruby 2.4.
import copy as cp
a = [[1,2,3], "abc"]
b = cp.copy(a)
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
a[0][1] = 4
a[1] = "def"
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
b = a[:]
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
a[0][1] = 3
a[1] = "abc"
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
Output result
id_a:4393106888, id_b:4393107272
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4391239728, id_b[1]:4391239728
[[1, 2, 3], 'abc'] [[1, 2, 3], 'abc']
id_a:4393106888, id_b:4393107272
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4392739984, id_b[1]:4391239728
[[1, 4, 3], 'def'] [[1, 4, 3], 'abc']
id_a:4393106888, id_b:4393112648
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4392739984, id_b[1]:4392739984
[[1, 4, 3], 'def'] [[1, 4, 3], 'def']
id_a:4393106888, id_b:4393112648
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4391239728, id_b[1]:4392739984
[[1, 3, 3], 'abc'] [[1, 3, 3], 'def']
If a mutable object holds another mutable object, which is a "shallow copy is not enough" case, you need to make a deep copy instead of a shallow copy to completely copy the value of b
to ʻa. There is. A deep copy can be achieved with
copy.deepcopy`.
import copy as cp
a = [[1,2,3], "abc"]
b = cp.deepcopy(a)
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
a[0][1] = 4
a[1] = "def"
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
Output result
id_a:4306767304, id_b:4306767688
id_a[0]:4306767176, id_b[0]:4306773064
id_a[1]:4304900144, id_b[1]:4304900144
[[1, 2, 3], 'abc'] [[1, 2, 3], 'abc']
id_a:4306767304, id_b:4306767688
id_a[0]:4306767176, id_b[0]:4306773064
id_a[1]:4306400400, id_b[1]:4304900144
[[1, 4, 3], 'def'] [[1, 2, 3], 'abc']
In the case of PHP, the value of the variable on the right side is copied to the value of the variable on the left side by assigning. It behaves like a deep copy of Python 3.
Note that PHP's $ a = & $ b;
reference assignment cannot be achieved with Python 3.
<?php
$a = [3];
$b = &$a;
$a = [5];
print_r($a);
print_r($b);
Output result
Array
(
[0] => 5
)
Array
(
[0] => 5
)
In the above example, even if $ a = [5];
, the reference values of $ b
and $ a
do not change.
In PHP, special characters and variables in the string were replaced in the case of double quotation marks, and not in the case of single quotation marks. In the case of Python3, the escape character is replaced and output in both cases. Prepend r
or R
to prevent replacement.
<?php
print("a\r\nb");
print('a\r\nb');
Output result
a
ba\r\nb
print("a\r\nb")
print('a\r\nb')
print(r"a\r\nb")
print(R"a\r\nb")
Output result
a
b
a
b
a\r\nb
a\r\nb
In PHP, when expressing a conditional expression, the notation $ a> 0 && $ a <10
. In Python3, I would like to set ʻa> 0 and a <10as well, but it can be simplified as
0 <a <10`.
Formats such as $ a = $ f?" Hello ":" world "
, which are familiar in PHP. In Pyhon3, the format is ʻa = "hello" if f else "world" . It is characterized by using ʻif
and ʻelse` in the ternary operator.
In Python3, formats such as ʻi ++ and ʻi--
will result in an error. Increment is ʻi + = 1 or ʻi-= 1
.
foreach
Foreach
and Python3
, which are indispensable in PHP, can do the same or better with for
as shown in the example below.
print("pattern 1")
for v in range(1, 4):
print(v)
print("Pattern 2")
for v in [x for x in range(4, 1, -1)]:
print(v)
print("Pattern 3")
for v in (1, 2, 3):
print(v)
print("Pattern 4")
for k, v in enumerate([1, 2, 3]):
print(k, v)
print("Pattern 5")
for k, v in {"a":1, "b":2}.items():
print(k, v)
print("Pattern 6")
for k in {"a":1, "b":2}.keys():
print(k)
print("Pattern 7")
for v in {"a":1, "b":2}.values():
print(v)
print("Pattern 8")
for v in [1, 2]:
print(v)
else:
print("else", v)
print("Pattern 9")
for v in [1, 2]:
print(v)
break
else:
print("else", v)
print("Pattern 10")
for v in [1, 2]:
print(v)
continue
else:
print("else", v)
print("Pattern 11")
for v1, v2, v3, v4 in zip([1, 2], (2, 1, 3), {1:"d", 2:"i", 3:"c"}, {"s", "e", "t"}):
print(v1, v2, v3, v4)
print("Pattern 12")
for v1, v2 in zip([1, 2], [3, 4, 5, 6]):
print(v1, v2)
print("Pattern 13")
import itertools as it
for v1, v2 in it.zip_longest([1, 2], [3, 4, 5, 6]):
print(v1, v2)
Output result
pattern 1
1
2
3
Pattern 2
4
3
2
Pattern 3
1
2
3
Pattern 4
0 1
1 2
2 3
Pattern 5
a 1
b 2
Pattern 6
a
b
Pattern 7
1
2
Pattern 8
1
2
else 2
Pattern 9
1
Pattern 10
1
2
else 2
Pattern 11
1 2 1 s
2 1 2 e
Pattern 12
1 3
2 4
Pattern 13
1 3
2 4
None 5
None 6
range
As an aside, range
has different boundary values between PHP and Python3.
<?php
print_r(range(0, 10, 2));
Output result
Array
(
[0] => 0
[1] => 2
[2] => 4
[3] => 6
[4] => 8
[5] => 10
)
print(list(range(0, 10, 2)))
Output result
[0, 2, 4, 6, 8]
There is a difference between PHP and Python3. The pattern is divided and described from the viewpoint of code comparison.
The function ʻinner has name resolution and can be called from the outside. Unless passed by reference, manipulating externally defined variables in the ʻinner
function has no effect on the outside. In addition, variables defined outside are treated as out of scope.
<?php
function outer($arg1)
{
$out1 = 3;
function inner($arg1, $arg2, &$arg3)
{
$arg1 += isset($out1) ? $out1 : -1;
$arg2 += 5;
$arg3 += 11;
print($arg1. " : inner arg1\n");
print($arg2. " : inner arg2\n");
print($arg3. " : inner arg3\n");
}
inner($arg1, $arg1, $out1);
print($arg1. " : outer arg1\n");
print($out1. " : outer out1\n");
}
outer(10);
$a = 13;
inner(1, 7, $a);
print($a. " : a");
Output result
9 : inner arg1
15 : inner arg2
14 : inner arg3
10 : outer arg1
14 : outer out1
0 : inner arg1
12 : inner arg2
24 : inner arg3
24 : a
Since the name of the ʻinner function is not resolved, it is necessary to get the return value of ʻouter
and call it in order to call the ʻinnerfunction from the outside. You can also access externally defined variables. As you can see from the result of
15: inner arg1, ʻout1
is[14]
, and the previous state is saved.
def outer(arg1):
out1 = [3]
def inner(arg1, arg2, arg3):
arg1 += -1 if out1 is None else out1[0]
arg2 += 5
arg3[0] += 11
print(arg1, "inner arg1", sep=" : ")
print(arg2, "inner arg2", sep=" : ")
print(arg3[0], "inner arg3", sep=" : ")
inner(arg1, arg1, out1)
print(arg1, "outer arg1", sep=" : ")
print(out1[0], "outer out1", sep=" : ")
return inner
f = outer(10)
a = [13]
f(1, 7, a)
print(a[0], "a", sep=" : ")
Output result
13 : inner arg1
15 : inner arg2
14 : inner arg3
10 : outer arg1
14 : outer out1
15 : inner arg1
12 : inner arg2
24 : inner arg3
24 : a
Anonymous functions are defined twice for convenience. The closure is returned by the ʻouter function, and the closure is defined by ʻarray_map
even in the closure. Externally defined variables can be accessed by using ʻuse`.
<?php
function outer($arg1)
{
$out = 2;
return function ($arg2) use ($arg1, $out) {
$a = [0 => $arg1, 1 => $arg1 * 2, 2 => $arg1 * 3];
return array_map(function ($k, $v) use ($arg2, $out) {
return ($v + $arg2) * $k + $out;
}, array_keys($a), array_values($a));
};
}
$f = outer(1);
print_r($f(3));
Output result
Array
(
[0] => 2
[1] => 7
[2] => 14
)
Return the closure with the ʻouterfunction as in PHP. Anonymous functions can be defined with
lambda`, but there is a limitation that variables cannot be defined.
def outer(arg1):
out = 2
def inner(arg2):
a = {0:arg1, 1:arg1 * 2, 2:arg1 * 3}
return map(lambda v: (v[1] + arg2) * v[0] + out, a.items())
return inner
f = outer(1)
print(list(f(3)))
Output result
[2, 7, 14]
Variable variables and functions that I used from time to time in PHP. Let's compare the code for PHP and Python3.
<?php
$a1 = "b1";
$b1 = "test1";
$a2 = "b2";
function b2 () {
print("test2");
}
print($$a1. "\n");
print($a2());
Output result
test1
test2
The usability is different from PHP, but the same thing can be achieved.
a1 = "b1"
b1 = "test1"
a2 = "b2"
def b2():
print("test2")
print(locals()[a1])
print(globals()[a1])
print(eval(a1))
locals()[a2]()
globals()[a2]()
eval(a2)()
Output result
test1
test1
test1
test2
test2
test2
I was confused when I was looking at the Python 3 code on GitHub, so a quick note. As the name suggests, it decorates.
def deco1(func):
def overwrite():
print("overwrite is called")
func()
return overwrite
def deco2(func):
import functools
@functools.wraps(func)
def overwrite(*args,**kwargs):
print("overwrite2 is called")
func(*args,**kwargs)
return overwrite
@deco1
def test1():
print('test1 is called')
test1()
print(test1.__name__)
@deco2
def test2():
print('test2 is called')
test2()
print(test2.__name__)
Here is organized in an easy-to-understand manner.
Annotations that you hear when using PHPDoc. It can be used with Python3, but it can also be used for various things such as generics. If you're new to these features, you'll get confused when you look at the Python code, so you want to know the features themselves. Click here for details (http://qiita.com/icoxfog417/items/c17eb042f4735b7924a3)
Higher-order functions available in both PHP and python3. There seems to be little difference.
map
First, for map
, a sample of the process of squared all the elements of the array.
<?php
$r1 = array_map(function($n) {
return $n ** 2;
}, range(1, 9));
print_r($r1);
Output result
Array
(
[0] => 1
[1] => 4
[2] => 9
[3] => 16
[4] => 25
[5] => 36
[6] => 49
[7] => 64
[8] => 81
)
It can also be realized by inclusion notation.
r11 = list(map(lambda n: n ** 2, range(1, 10)))
r12 = [n ** 2 for n in range(1, 10)]
print(r11)
print(r12)
Output result
[1, 4, 9, 16, 25, 36, 49, 64, 81]
[1, 4, 9, 16, 25, 36, 49, 64, 81]
filter A sample that extracts elements with only even values.
<?php
$r2 = array_filter(range(1, 9), function($n) {
return $n % 2 == 0;
});
print_r($r2);
Output result
Array
(
[1] => 2
[3] => 4
[5] => 6
[7] => 8
)
It can be realized by the inclusion notation as well as map
.
r21 = list(filter(lambda n: n % 2 == 0, range(1, 10)))
r22 = [n for n in range(1, 10) if n % 2 == 0]
print(r21)
print(r22)
Output result
[2, 4, 6, 8]
[2, 4, 6, 8]
reduce It feels strange to translate it as convolution or decrease, so I interpret it that way. Is it ʻinject` in ruby? Here is a sample that lists the elements as integers.
<?php
$r3 = array_reduce(range(1, 9), function($a, $b) {
return $a * 10 + $b;
}, 0);
print_r($r3);
Output result
123456789
Requires functools
.
from functools import reduce
r3 = reduce(lambda a, b: a * 10 + b, range(1, 10))
print(r3)
Output result
123456789
PHP has more array-type functions, but I often wonder what to use and where to use it. ʻArray_walk` is often used as the main.
To use a regular expression in PCRE
format, PHP requires the pattern to be enclosed in delimiters. Taking a 4-digit number as an example, the pattern is expressed as '/ \ d {4} /'
.
On the other hand, in Python3, first, r
is added to the character string that becomes the pattern. By doing so, r" \ n "
is not treated as a line feed code, but can be interpreted as a character string of \
(backslash) and n
. If r
is not added, it must be"\\\\ n"
. Also, the regular expression pattern is compiled and used as a regular expression object with re.compile ('/ \ d {4} /')
(Requires ʻimport re`).
A simple comparison table between PHP and Python 3 looks like this:
PHP | Python | Remarks |
---|---|---|
preg_match | re.findall | re.If a set is specified in the pattern, findall will make the elements of the array a tuple, and the set elements will be there. |
re.match | re.match confirms match only at the beginning | |
re.search | re.search can be anywhere in the string | |
preg_replace | re.sub | The first matching character is${1} (PHP)、\1 Different from (Python) |
preg_replace_callback | re.The sub argument repl can be a string or a function | |
preg_split | re.split |
The handling of regular expressions in PHP and Python3 is summarized in here.
private、protected Python 3 has neither private nor protected. Therefore, add one or two underscores (_) for customary operation.
class Test(object):
def __init__(self):
self.value = "value"
self._value = "_value"
self.__value = "__value"
def method(self): print("method")
def _method(self): print("_method")
def __method(self): print("__method")
t = Test()
print(t.value)
print(t._value)
print(t._Test__value)
t.method()
t._method()
t._Test__method()
Output result
value
_value
__value
method
_method
__method
Static methods are familiar when using PHP. The difference from the static method is whether it receives the Class itself as the first argument. It is easy to determine from which class it is being executed. Unlike PHP, it can be called from an instance of a class. A decorator is required for both.
class MyParent(object):
var = "parent"
@staticmethod
def static_test(called):
print(called, MyParent.var)
@classmethod
def class_test(cls, called):
print(called, cls.var)
class MyChild(MyParent):
var = "child"
def test(self):
print("child test")
MyParent.class_test("Parent")
MyParent.static_test("Parent")
MyParent.class_test("Child")
MyParent.static_test("Child")
p = MyParent()
c = MyChild()
p.static_test(p.__class__)
p.class_test(p.__class__)
c.static_test(c.__class__)
c.class_test(c.__class__)
Output result
Parent parent
Parent parent
Child parent
Child parent
<class '__main__.MyParent'> parent
<class '__main__.MyParent'> parent
<class '__main__.MyChild'> parent
<class '__main__.MyChild'> child
When implementing a class method like Python3 in PHP, it looks like this:
In this case, the same result can be obtained by changing new static ()
to new self ()
.
<?php
class MyParent
{
public $var = "parent";
public static function class_method($called) {
$cls = new static();
print($called. " ". $cls->var. "\n");
}
}
class MyChild extends MyParent
{
public $var = "child";
}
MyParent::class_method("Parent");
MyChild::class_method("Child");
Output result
Parent parent
Child child
Python 3 has a with syntax.
It's similar to PHP.
file = open("filename")
try:
print(file.read())
finally:
file.close()
It will be very simple.
with open("filename") as file:
print(file.read())
You can handle class instances with with syntax just by defining __enter__
and __exit__
in the class.
class WithTest:
def __init__(self, name):
self._name = name
def print(self):
print(self._name)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
print("end of with statement!")
with WithTest("With Statement!") as t:
t.print()
Output result
With Statement!
end of with statement!
Iterator that is relatively used for reading and processing files such as csv line by line, extracting tuples from a table and processing them one by one. Both PHP and Python have iterators and generators, but I will actually prepare the code and try to see if there is a difference.
Python3 can be implemented in the same way as PHP. However, Python 3 has a built-in function as standard.
It's a bit annoying because it implements the Iterator interface, so you only need to define next
and other methods.
<?php
class MyIterator implements Iterator
{
private $var = [];
public function __construct($array)
{
if (is_array($array)) {
$this->var = $array;
}
}
public function rewind()
{
reset($this->var);
}
public function current()
{
return current($this->var);
}
public function key()
{
return key($this->var);
}
public function next()
{
return next($this->var);
}
public function valid()
{
$key = key($this->var);
return ($key !== NULL && $key !== FALSE);
}
}
$iter = new MyIterator([1, 2, 3, 4, 5]);
foreach ($iter as $k => $v) {
print("$k: $v\n");
}
Output result
0: 1
1: 2
2: 3
3: 4
4: 5
It can be implemented more simply than PHP, but be careful because you need to throw StopIteration
when the process is completed.
class MyIterator:
def __init__(self, *numbers):
self._numbers = numbers
self._i = 0
def __iter__(self):
return self
def __next__(self):
if self._i == len(self._numbers):
raise StopIteration()
v = self._numbers[self._i]
self._i += 1
return v
iter = MyIterator(1, 2, 3, 4, 5)
for i, num in enumerate(iter):
print("{0}:{1}".format(i, num))
Output result
0:1
1:2
2:3
3:4
4:5
Generators are also available in Python 3 and PHP (5.5+). In the sample here, the following files are read.
numbers.txt
zero
one
two
three
four
five
The implementation method is almost the same for PHP and Python3.
<?php
function my_generator($name)
{
$file = fopen($name, "r");
if ($file) {
while ($line = fgets($file)) {
yield $line;
}
}
fclose($file);
}
$g = my_generator("numbers.txt");
foreach ($g as $k => $v) {
print($k. ":". $v);
}
Output result
0:zero
1:one
2:two
3:three
4:four
5:five
def my_generator(name):
with open(name) as lines:
for line in lines:
yield line
g = my_generator("numbers.txt")
for k, v in enumerate(g):
print("{0}:{1}".format(k, v), end="")
Output result
0:zero
1:one
2:two
3:three
4:four
5:five
It is the same in that it is sent by send
, but the usability is different between PHP and Python.
An image that sends data to yield
. The output result is the same as the "basic implementation method".
<?php
function my_generator()
{
$k = 0;
while (true) {
$v = yield;
print($k++. ":". $v);
}
}
$g = my_generator();
$file = fopen("numbers.txt", "r");
if ($file) {
while ($line = fgets($file)) {
$g->send($line);
}
}
An image that sends data to the variable specified by yield
. It seems to be different from PHP in that you need to execute __next__
once to move to the position of yield
. The output result is the same as the "basic implementation method".
def my_generator():
k, v = 0, ""
while True:
v = yield v
print("{0}:{1}".format(k, v), end="")
k += 1
g = my_generator()
g.__next__()
with open("numbers.txt") as lines:
for line in lines:
g.send(line)
Recursive logic can be realized with yield from
.
Implemented from PHP7. The output result is the same as the "basic implementation method". There is not much merit in terms of reading files, but in the case of operations such as arrays, it seems that it can be equivalent to Python 3.
<?php
function my_generator($name)
{
$from = function () use ($name) {
$file = fopen($name, "r");
if ($file) {
while ($line = fgets($file)) {
yield $line;
}
}
fclose($file);
};
yield from $from();
}
$g = my_generator("numbers.txt");
foreach ($g as $k => $v) {
print($k. ":". $v);
}
The output result is the same as the "basic implementation method". Since the loop is no longer required from the "basic implementation method", it has become simple.
def my_generator(name):
with open(name) as lines:
yield from lines
g = my_generator("numbers.txt")
for k, v in enumerate(g):
print("{0}:{1}".format(k, v), end="")
interface、abstract There is no ʻinterface` like PHP in Python 3. Since Python3 can inherit multiple times, it seems unnecessary in the first place. In Python3, abstract classes can be implemented using the ABC (Abstract Base Class) module. In addition, Trait seems to be unnecessary for Python 3 because multiple inheritance is possible.
To provide an abstract method, the class metaclass (specified by __metaclass__
) is ʻABCMeta` or inherits it. From the output result below, you can also implement an abstract method in an abstract class, and even if it is undefined in a subclass, no error will occur.
python
from abc import *
class MyAbstract(object):
__metaclass__ = ABCMeta
@abstractmethod
def test1(self):
print("method")
@staticmethod
@abstractmethod
def static_test():
print("static_method")
@classmethod
@abstractmethod
def class_test(cls):
print("class_method")
class Test(MyAbstract):
pass
MyAbstract.static_test()
MyAbstract.class_test()
Test.static_test()
Test.class_test()
p = MyAbstract()
p.test1()
t = Test()
t.test1()
Output result
static_method
class_method
static_method
class_method
method
method
If you expect the same behavior as PHP, it seems that similar operation can be done by defining as follows in the method of the parent class.
def test1(self):
raise NotImplementedError("error message")
Another method is to prepare a class that overrides the class method __subclasshook__
as shown below and check whether the method is defined by the built-in function ʻissubclacss. The check passes by doing
register`.
from abc import ABCMeta
class MyAbstract(metaclass=ABCMeta):
@classmethod
def __subclasshook__(cls, C):
if cls is MyAbstract:
if any("test" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
class A(object):
pass
class B(object):
def test(self):
print("test")
print(issubclass(A, MyAbstract))
print(issubclass(B, MyAbstract))
MyAbstract.register(A)
print(issubclass(A, MyAbstract))
Output result
False
True
True
PHP's magic method is the so-called Python3 data model special method name. /3.6/reference/datamodel.html#special-method-names). There are many similar items, such as PHP's __toString
, which corresponds to Python3's __str__
.
You can get the properties of an object with get_object_vars
.
<?php
class Magic
{
public function __get($name)
{
return 0;
}
public function __call($name, $arguments)
{
print($arguments[0]. "\n");
}
}
$m = new Magic();
print($m->x. "\n");
$m->x = 10;
print($m->x. "\n");
print($m->test(20));
print_r(get_object_vars($m));
Output result
0
10
20
Array
(
[x] => 10
)
Since the instance variable is stored in __dict__
, its contents can be obtained by the built-in function vars
.
class Magic(object):
def __getattr__(self, name):
class Callable(int):
def __call__(self, *arguments):
print(arguments[0])
return Callable(0)
m = Magic()
print(m.x)
m.x = 10
print(m.x)
m.test(20)
print(vars(m))
Output result
0
10
20
{'x': 10}
Setter/Getter As an aside, in Python3 you can also define Setters / Getters in the following ways.
class Magic(object):
def __init__(self):
self._x = 0
self._y = 0
def getx(self):
return self._x
def setx(self, value):
self._x = value
x = property(getx, setx)
@property
def y(self):
return self._y
@y.setter
def y(self, value):
self._y = value
m = magic()
print(m.x)
print(m.y)
m.x = 10
m.y = 20
print(m.x)
print(m.y)
Output result
0
0
10
20