Summary of the differences between PHP and Python

A reminder about the difference between PHP and Python 3

The difference between PHP and Python is summarized as a memorandum from the perspective of PHP.

Put short

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).

Interactive mode

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.

Array

List, tuple, dictionary, set

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.

List

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.

List slice

PHP has ʻarray_slice, but Python 3 has more useful features. By setting ʻa = b [m: n], the n-1th element from the mth 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 everym`.

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.

From string to list

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']

Tuple

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.

Dictionary (dict)

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`.

Set

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.

Examples of using lists, tuples, dictionaries, and sets in Python3

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.

Substitution

Immutable / Mutable

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.

Python3 assignment

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.

For immutable objects

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

For mutable objects

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]
Shallow copy

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]
Cases where shallow copying is not enough

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']
Deep copy

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']

PHP assignment

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.

Syntax related

Double quotes, single quotes

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.

For PHP

<?php
print("a\r\nb");
print('a\r\nb');

Output result


a
ba\r\nb

For Python 3

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

Inequality sign

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 as0 <a <10`.

Ternary operator

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.

Increment decrement

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.

Python3 for example

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.

For PHP
<?php
print_r(range(0, 10, 2));

Output result


Array
(
    [0] => 0
    [1] => 2
    [2] => 4
    [3] => 6
    [4] => 8
    [5] => 10
)
For Python 3
print(list(range(0, 10, 2)))

Output result


[0, 2, 4, 6, 8]

closure

There is a difference between PHP and Python3. The pattern is divided and described from the viewpoint of code comparison.

Function definition within a function

For PHP

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
For Python 3

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 of15: 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 function

For PHP

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
)
For Python 3

Return the closure with the ʻouterfunction as in PHP. Anonymous functions can be defined withlambda`, 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, variable functions

Variable variables and functions that I used from time to time in PHP. Let's compare the code for PHP and Python3.

For PHP

<?php

$a1 = "b1";
$b1 = "test1";

$a2 = "b2";

function b2 () {
    print("test2");
}

print($$a1. "\n");
print($a2());

Output result


test1
test2

For Python 3

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

Decorator

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.

Annotation

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)

List operation using map, filter, reduce

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.

For PHP
<?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
)
For Python 3

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.

For PHP
<?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
)
For Python 3

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.

For PHP
<?php

$r3 = array_reduce(range(1, 9), function($a, $b) {
    return $a * 10 + $b;
}, 0);
print_r($r3);

Output result


123456789
For Python 3

Requires functools.

from functools import reduce

r3 = reduce(lambda a, b: a * 10 + b, range(1, 10))
print(r3)

Output result


123456789

Other

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.

Regular expressions

Introduction

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`).

About function comparison

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)、\1Different from (Python)
preg_replace_callback re.The sub argument repl can be a string or a function
preg_split re.split

Other

The handling of regular expressions in PHP and Python3 is summarized in here.

class related

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

Class methods and static methods

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

Supplement

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

with syntax

Python 3 has a with syntax.

Legacy writing

It's similar to PHP.

file = open("filename")
try:
    print(file.read())
finally:
   file.close()

How to write using the with syntax

It will be very simple.

with open("filename") as file:
  print(file.read())

Make class instances correspond to with syntax

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 and generator

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.

Iterator

Python3 can be implemented in the same way as PHP. However, Python 3 has a built-in function as standard.

For PHP

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
For Python 3

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

generator

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
Basic implementation method

The implementation method is almost the same for PHP and Python3.

For PHP
<?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
For Python 3
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
Send data with each call

It is the same in that it is sent by send, but the usability is different between PHP and Python.

For PHP

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);
    }
}
For Python 3

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)
Sub-generator

Recursive logic can be realized with yield from.

For PHP

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);
}
For Python 3

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.

Implementation example of abstract method in Python3

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")

Virtual subclass

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

Magic method

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__.

Access to undefined or non-accessible property methods

For PHP

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
)
For Python 3

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

Recommended Posts

Summary of the differences between PHP and Python
Summary of differences between Python and PHP (comparison table of main items)
A rough summary of the differences between Windows and Linux
The answer of "1/2" is different between python2 and 3
Python --Explanation and usage summary of the top 24 packages
The story of Python and the story of NaN
Differences between Python, stftime and strptime
Summary of Python indexes and slices
I tried to enumerate the differences between java and python
Summary of Differences Between Ruby on Rails and Django ~ Basics ~
Differences in authenticity between Python and JavaScript
Differences between Ruby and Python in scope
Differences in syntax between Python and Java
Difference between PHP and Python finally and exit
[Basic grammar] Differences between Ruby / Python / PHP
Differences in multithreading between Python and Jython
Differences between Ruby and Python (basic syntax)
Correspondence summary of array operation of ruby and python
Specifying the range of ruby and python arrays
the zen of Python
About the difference between "==" and "is" in python
[Python] Summary of conversion between character strings and numerical values (ascii code)
Installation of Python3 and Flask [Environment construction summary]
Compare the speed of Python append and map
Summary of Python arguments
I / O related summary of python and fortran
About the * (asterisk) argument of python (and itertools.starmap)
A discussion of the strengths and weaknesses of Python
Differences in string processing between Python, Ruby, JS, PHP (combination and variable expansion)
Get the last element of the array by splitting the string in Python and PHP
The story of Python without increment and decrement operators.
The process of installing Atom and getting Python running
[Python] Type Error: Summary of error causes and remedies for'None Type'
Difference between Ruby and Python in terms of variables
Indent behavior of json.dumps is different between python2 and python3
Visualize the range of interpolation and extrapolation with python
Referencing and changing the upper bound of Python recursion
I checked out the versions of Blender and Python
PHP and Python samples that hit the ChatWork API
EP 3 Know the Differences Between bytes, str, and unicode
Visualization of the connection between malware and the callback server
Summary of the basic flow of machine learning with Python
[Python] Summary of how to specify the color of the figure
Summary of date processing in Python (datetime and dateutil)
Towards the retirement of Python2
Summary of python file operations
Summary of Python3 list operations
About the ease of Python
About the features of Python
Source installation and installation of Python
The Power of Pandas: Python
The timing when the value of the default argument is evaluated is different between Ruby and Python.
[Python] Heron's formula functionalization and calculation of the maximum area
[python] Summary of how to retrieve lists and dictionary elements
[python] plot the values ​​before and after the conversion of yeojohnson conversion
[Python] Summary of how to use split and join functions
Summary of Hash (Dictionary) operation support for Ruby and Python
The process of making Python code object-oriented and improving it
The websocket of toio (nodejs) and python / websocket do not connect.
I want to know the features of Python and pip
[Tips] Problems and solutions in the development of python + kivy