PythonとPHPの基本構文まとめ

# Introduction
新しくPHPを学ぶことになった
基本構文を理解するため慣れ親しんだPythonとの比較をまとめる

参考サイト
- [Pythonチュートリアル](https://docs.python.org/ja/3/tutorial/index.html)
- [PHP言語リファレンス](https://www.php.net/manual/ja/langref.php)


# コメント
- 'C', 'C++' および Unix シェル型（Perl 型）のコメントをサポート
- <$php  　?>タグでコードを囲む必要あり（本記事では以降タグは省略）

```php:php
<?php
// comment

# comment

/*
comment1
comment2
*/
?>
```


```py:python
# comment

'''
comment1
comment2
'''
```

# 出力
- `echo`で出力できるが改行する場合は改行コード`"\n"`が必要
- 改行コードはシングルクォーテーション`'`では単なる文字列として認識される

```php:php
echo 'hello', "\n";  #Out: hello
echo 'world', '\n';  #Out: world\n
```

```py:python
print('hello')        #Out: hello
print('world', '\n')  #Out: world
```

# 変数とデータ型

## 変数定義
- 変数の先頭は`$`マーク
- 各コードの末尾は`;`
- bool型は`True` `TRUE` `true` どれでも可（pythonは`True`のみ）
- 空文字列は`NULL`（pythonは`None`）
- 型の確認は`var_dump()`


```php:php
$a_bool = True;   // bool
$a_str  = "foo";  // string
$a_str2 = 'foo';  // string
$a_int = 12;      // int
$a_float = 12.5;  // float
$a_null = NULL;   // NUll

var_dump($a_bool);  //Out: bool(true)
```

```py:python
a_bool = True   # bool
a_str  = "foo"  # string
a_str2 = 'foo'  # string
a_int = 12      # int
a_float = 12.5  # float
a_none = None   # NoneType

print(type(a_none))  #Out: <class 'bool'>
```



## 文字列
- `.`で文字列を結合
- 文字列を繰り返すには`str_repeat()`関数を使う必要あり
```php:php
$s1 = 'hello';
$s2 = 'world';

echo ($s1.$s2), "\n";           #Out: helloworld
echo $s1[0], "\n";              #Out: h
echo str_repeat($s1, 3), "\n";  #OUt: hellohellohello
```

```py:python
s1 = 'hello'
s2 = 'world'

print(s1+s2)  #Out: helloworld
print(s1[0])  #Out: h
print(s1*3)   #OUt: hellohellohello
```

## 配列（リスト）と連想配列（辞書型）
- 配列は`[]`または`arrary()`で定義
- 配列の中身に異なるデータ型の混在は不可（pythonのリストは混在可）
- 連想配列であれば異なるデータ型を扱える（pythonでいう辞書型）
- 配列は要素番号，連想配列はキーでアクセス
- 配列の要素数は`count()`で取得（pythonは`len()`）

```php:php
$a_array1 = [1,2,2];
$a_array2 = array('apple','peach', 'banana');

$a_array3 = array(
    1 => 'apple',
    2 => 'peach',
    3 => 'banana'
);
    
$a_array4  = [
    'fruits' => 'apple',
    'price' => 100,
    'bool' => TRUE
];


echo $a_array1[0], "\n";        #Out: 1
echo $a_array2[2], "\n";        #Out: banana
echo $a_array3[3], "\n";        #Out: banana
echo $a_array4["price"], "\n";  #Out: 100
echo count($a_array1), "\n";    #OUt: 3
```

```py:python
a_list1 = [1,2,'s']
a_list2 = ['apple', 'peach', 'banana']
a_dict1 = {
    1: 'apple',
    2: 'peach',
    3: 'banana'
}
a_dict2 = {
    'fluits': 'apple',
    'price': 100,
    'bool': True
}
print(a_list1[0])        #Out: 1
print(a_list2[2])        #Out: banana
print(a_dict1[3])        #OUt: banana
print(a_dict2['price'])  #Out: 100
print(len(a_list1))      #Out: 3
```

# 演算子

## 算術演算子と代入演算子
- 切り捨て徐算は`floor()`関数を使用する必要あり
- `++`などのインクリメントが可能
```php:php
$a = 10;
$b = 3;

echo ($a+$b), "\n";       # 加算　OUt: 13 
echo ($a-$b), "\n";       # 減算  Out: 7
echo ($a*$b), "\n";       # 乗算  Out: 30
echo ($a/$b), "\n";       # 徐算  Out: 3.3333333333333
echo floor($a/$b), "\n";  # 切り捨て徐算  Out: 3
echo ($a%$b), "\n";       # 剰余  OUt: 1
echo ($a**$b), "\n";      # 累乗  Out: 1000

$a++;
$a+=1;
echo $a, "\n";  #Out: 12
```

```py:python
a = 10
b = 3

print(a+b)   # 加算　OUt: 13 
print(a-b)   # 減算  Out: 7
print(a*b)   # 乗算  Out: 30
print(a/b)   # 徐算  Out: 3.3333333333333335
print(a//b)  # 切り捨て徐算  Out: 3
print(a%b)   # 剰余  OUt: 1
print(a**b)  # 累乗  Out: 1000

a += 1
print(a)  #Out: 11
```

## 比較演算子
- `==`だとデータ型が異なっても等しいと判定される
- データ型も含めて等しいかを判定するには`===`を使用
```php:php
$a = 10;
$b = 1;
$s = '10';

var_dump($a==$b);   // bool(false)
var_dump($a==$s);   // bool(true)
var_dump($a===$s);  // bool(false)
var_dump($a!=$b);   // bool(true)
var_dump($a>$b);    // bool(true)
var_dump($a<=$b);   // bool(false)
```

```py:python
a = 10
b = 1
s = '10'

print(a==b)  # False
print(a==s)  # False
print(a!=b)  # True
print(a>b)   # True
print(a<=b)  # False
```


## 論理演算子
- 論理積と論理和は`and`と`or`で両言語同じ
- `&&`や`||`を使う場合は2つ必要
- 否定は`!`を使用（`not`は使えない）
```php:php
$a = true;
$b = false;

var_dump($a and $b);  //Out: bool(false)
var_dump($a && $b);   //Out: bool(false)
var_dump($a or $b);   //Out: bool(true)
var_dump($a || $b);   //Out: bool(true)
var_dump(! $a);       //Out: bool(false)
```

```py:python
a = True
b = False

print(a and b)  #Out: False
print(a or b)   #Out: True
print(not a)    #Out: False
```

# 条件分岐

## if文
- `()`内に条件式を記述
- `()`内の条件に一致したら`{}`内の処理を実行

```php:php
$a = 10;
$b = 1;

if ($a > $b) {
    echo "a>b", "\n";
} elseif ($a === $b) {
    echo "a=b", "\n";
} else {
    echo "a<b", "\n";
}  //Out: a>b
```

```py:python
a = 10
b = 1

if a > b:
    print('a>b')
elif a == b:
    print('a=b')
else:
    print('a<b')
#Out: a>b 
```

## switch文
- `case`に一致したら`break`まで実行される
- pythonに`switch`文はないがバージョン3.10から追加されたmatch文では同じことができるらしい

```php:php
$a = 5;

switch ($a) {
    case 0:
        echo 'a=0';
        break;
    case 1:
        echo 'a=1';
        break;
    case 2:
        echo 'a=2';
        break;
    default:
       echo $a;
}  //Out: 5
```
# 繰り返し処理
## for文
- `for (式1; 式2; 式3)`のように定義
- pythonのように配列の要素を直接取り出してループすることはできない

```php:php
$a_array = ['apple', 'peach', 'banana'];

for ($i=0, $size=count($a_array) ; $i<$size; $i++){
    echo $a_array[$i], "\n";
}
/*Out:
apple
peach
banana
*/

for ($i=0 ; $i<3; $i++){
    echo $i, "\n";
}
/*Out:
0
1
2
*/
```

```py:python
a_list = ['apple', 'peach', 'banana']

for s in a_list:
    print(s)
'''Out:
apple
peach
banana
'''
    
for i in range(3):
    print(i)
'''Out:
0
1
2
'''
```

## foreach文
- 配列の要素の取り出しは`foreach`文を使用
- phpの連想配列とpythonの辞書型で少し違いがあるため注意

```php:php
$a_array1 = array('apple','peach', 'banana');
    
$a_array2 = [
    'fruits' => 'apple',
    'price' => 100,
    'bool' => TRUE
];

foreach($a_array1 as $value){
    echo $value, "\n";
}
/*Out:
apple
peach
banana
*/

foreach($a_array1 as $key => $value){
    echo $key, ":", $value, "\n";
}
/*Out:
0:apple
1:peach
2:banana
*/

foreach($a_array2 as $value){
    echo $value, "\n";
}
/*Out:
apple
100
1
*/

foreach($a_array2 as $key => $value){
    echo $key, ":", $value, "\n";
}
/*Out:
fruits:apple
price:100
bool:1
*/
```

```py:python
a_list = ['apple', 'peach', 'banana']

a_dict = {
    'fluits': 'apple',
    'price': 100,
    'bool': True
}

for value in a_list:
    print(value)
'''Out:
apple
peach
banana
'''
    
for key, value in enumerate(a_list):
    print(key, ':', value, sep='')
'''Out:
0:apple
1:peach
2:banana
'''

for key in a_dict:
    print(key)
'''Out:
fluits
price
bool
'''

for key, value in a_dict.items():
    print(key, ':', value, sep='')
'''Out:
fluits:apple
price:100
bool:True
'''
```


# while文　do while文　break continue
- `while` `break` `continue`は基本的にpythonと同じ
- pythonでは使えない`do while`が使用可能

```php:php
$a = 0;
while(true){
    $a++;
    if($a%2 === 0){
        continue;
    }
    if($a == 5){
        echo "\n";
        break;
    }
    echo $a;
}  //Out: 13


$i = 0;
do {
    echo $i;
} while ($i > 0);  //Out: 0
```

```py:python
a = 0
while(True):  #Out: 13
    a+=1
    if a%2 == 0 :
        continue
    if a == 5 :
        break
    print(a, end='')
```

# 関数
- `function`で定義
```php:php
function add($x, $y=10) {
    return $x + $y;
}

echo add(5), "\n";    //Out: 15
echo add(5,5), "\n";  //Out: 10
```

```py:python
def add(x, y=10):
    return x+y
    
print(add(5))    #Out: 15
print(add(5,5))  #Out: 10
```

# クラス
## クラス定義とインスタンス生成
- 同クラス内のプロパティにアクセスするには`$this->`を使用
- インスタンスの生成は`new`
- プロパティとメソッドの呼び出しはアロー演算子`->`を使用

```php:php
class MyClass{
    
    public $a = 'apple';

    public function display() {
        echo $this->a;
    }
}

$instance = new MyClass();
echo $instance->a, "\n";  //Out: apple
$instance->display();    //Out: apple
```

```py:python
class MyClass:

    a = 'apple'
    
    def display(self):
        print(self.a)

instance = MyClass()
print(instance.a)   #OUt: apple
instance.display()  #Out: apple
```

## コンストラクタ（イニシャライザ）
- pythonでいう`__init__`はphpだと`__construct`になる

```php:php
class MyClass2{
    
    public $a;
    
    function __construct($a){
        echo 'call construct', "\n";
        $this->a = $a;
    }
}

$instance = new MyClass2('apple');  //Out: call construct
echo $instance->a, "\n";            //Out: apple
```

```py:python
class MyClass2:
    
    def __init__(self, a):
        print('call init')
        self.a = a

instance = MyClass2('apple')  #Out: call init
print(instance.a)             #Out: apple
```

## クラス変数
- クラス変数は`static`で定義
- 同クラス内のクラス変数には`self::`でアクセス
- クラス外からは`::`でアクセス
```php:php
class MyClass3{
    
    public static $a = 'apple';

    public function display() {
        echo self::$a, "\n";
    }
}

echo Myclass3::$a, "\n";   //Out: apple
$instance = new MyClass3();
echo $instance::$a, "\n";  //Out: apple
$instance->display();      //Out: apple
```

```py:python
class MyClass3:
    
    a = 'apple'
    
    def display(self):
        print(self.a)

print(MyClass3.a)   #Out: apple
instance = MyClass3()
print(instance.a)     #Out: apple
instance.display()    #Out: apple
```

## クラスメソッド
- 定義方法やアクセス方法はクラス変数と同様

```php:php
class MyClass4{
    
    function __construct(){
        self::sayHello();
    }
    
    public static function sayHello(){
        echo 'Hello', "\n";
    }
}

MyClass4::sayHello();        //Out: Hello
$instance = new MyClass4();  //Out: Hello
$instance->sayHello();       //Out: Hello
```

```py:python
class MyClass4:
    
    def __init__(self):
        self.sayHello()
        
    @classmethod
    def sayHello(cls):
        print('Hello')

MyClass4.sayHello()    #Out: Hello
instance = MyClass4()  #Out: Hello
instance.sayHello()    #Out: Hello
```


## オブジェクト定数
- 定数は`const`で定義し慣例として大文字にする
- pythonでは定数の定義はできないため書き換えが発生してしまう

```php:php
class MyClass5{
    const NAME = 'Ken';
}

echo MyClass5::NAME, "\n";    //Out: Ken
$instance = new MyClass5();  
echo $instance::NAME, "\n";   //Out: Ken

$instance->NAME = 'J';

echo MyClass5::NAME, "\n";   //Out: Ken
echo $instance::NAME, "\n";  //OUt: Ken
```

```py:python
class MyClass5:
    NAME = 'Ken'

print(MyClass5.NAME)   #Out: Ken
instance = MyClass5()   
print(instance.NAME)   #Out: Ken

instance.NAME = 'J'

print(instance.NAME)   #Out: J
print(MyClass5.NAME)   #Out: Ken
```

## 継承
- `extends`を使用して親クラスを継承
- `parent::`で親クラスのメソッドを使用する

```php:php
class MyClass6{
    
    public $my_name = 'Ken';
    
    public function say(){
        echo 'My name is ', $this->my_name, "\n";
    }
}

class SubClass6 extends MyClass6{
    public $sub_name = 'K';
    
    public function say_sub(){
        echo 'Sub name is ', $this->sub_name, "\n";
    }
    
    public function say_my_sub(){
        parent::say();
        $this->say_sub();
    }
    
}

$instance = new SubClass6();
$instance->say();           //Out: My name is Ken
$instance->say_sub();       //OUt: Sub name is K
$instance->say_my_sub();   
/*OUt:
My name is Ken
Sub name is K
*/
```

```py:python
class MyClass6:
    
    my_name = 'Ken'
    
    def say(self):
        print(f'My name is {self.my_name}')

class SubClass6(MyClass6):
    
    sub_name = 'K'
    
    def say_sub(self):
        print(f'Sub name is {self.sub_name}')
        
    def say_my_sub(self):
        super().say()
        self.say_sub()

instance = SubClass6()
instance.say()          #Out: MY name is Ken
instance.say_sub()      #Out: Sub name is K
instance.say_my_sub()
'''OUt:
My name is Ken
Sub name is K
```

## オーバーライド
- Python同様親クラスのメソッド名と同じ名前のメソッドを定義すればよい

```php:php
class MyClass7{
    
    public $my_name = 'Ken';
    
    public function say(){
        echo 'My name is ', $this->my_name, "\n";
    }
}

class SubClass7 extends MyClass7{
    public $sub_name = 'K';
    
    public function say(){
        echo 'Sub name is ', $this->sub_name, "\n";
    }
    
    public function say_my(){
        parent::say();
    }
    
}

$instance = new SubClass7();
$instance->say();           //Out: Sub name is K
$instance->say_my();       //OUt: My name is Ken
```

```py:python
class MyClass7:
    
    my_name = 'Ken'
    
    def say(self):
        print(f'My name is {self.my_name}')

class SubClass7(MyClass7):
    
    sub_name = 'K'
    
    def say(self):
        print(f'Sub name is {self.sub_name}')
        
    def say_my(self):
        super().say()

instance = SubClass7()
instance.say()          #Out: Sub name is K
instance.say_my()      #Out: My name is Ken
```

## アクセス権
- `public`はどこからでもアクセス可能
- `protected`は子クラスまでアクセス可能（pythonだとアンダーバー1つ`_`で定義するようだが実際はどこからでもアクセス可能）
- `private`はクラス内のみアクセス可能（pythonだとアンダーバー2つ`__`）

```php:php
class MyClass8{
    
    public $pub = 'public';
    protected $pro = 'protected';
    private $pri = 'private';
    
    public function get_pri(){
        return $this->pri;
    }
}

class SubClass8 extends MyClass8{
    
    public function get_pro(){
        return $this->pro;
    }
    
}

$instance = new SubClass8();
echo $instance->pub, "\n";        //Out: public
echo $instance->get_pro(), "\n";  //Out: protected
echo $instance->get_pri(), "\n";  //Out: private
```

```py:python
class MyClass8:
    
    pub = 'public'
    _pro = 'protected'
    __pri = 'private'
    
    def get_pri(self):
        return self.__pri

class SubClass8(MyClass8):
    pass

instance = SubClass8()
print(instance.pub)        #Out: public
print(instance._pro)       #Out: protected
print(instance.get_pri())  #Out: private
```

# Conclusion
Pythonに慣れた人がPHPを書く際は変数定義の`$`や文末の`;`を忘れないよう注意が必要だと感じた．
クラス変数やメソッドの呼び出しがすべて`.`でできる点もPythonの良いところだと感じた．
エラー処理やファイル読込などはまた必要になった時にまとめようと思う．