🐍

PHPプログラマのためのPythonガイド

2025/03/12に公開

PHPのバックグラウンドを持ちながらPythonに挑戦するエンジニアのために、両言語の構文や機能を比較解説します。この記事では、PHP 8.xとPython 3.xの基本的な構文の違いから、よく使われる機能の対応表まで、実践的なコード例とともに紹介します。

目次

  1. 基本構文
  2. 制御構文
  3. オブジェクト指向プログラミング
  4. 例外処理
  5. 文字列処理
  6. 配列と連想配列
  7. 日付と時間の操作
  8. ファイル操作
  9. 正規表現
  10. よく使う便利機能

基本構文

スクリプト構造

PHP:

<?php
// PHPコードは <?php タグで始まります
echo "Hello, World!";

// 終了タグは省略可能(むしろ推奨)

Python:

# Pythonはタグが不要
print("Hello, World!")

# インデントがスコープを表します

変数定義

PHP:

<?php
$name = "John";  // 変数は$ で始まる
$age = 30;       // 型宣言は不要
$isActive = true;

// PHP 7.4以降では型ヒントが使える
string $profession = "Developer";

Python:

name = "John"    # 変数に$ は不要
age = 30         # 型宣言は不要
is_active = True # 真偽値は大文字始まり

# 型ヒントを使う場合(Python 3.5以降)
profession: str = "Developer"

コメント

PHP:

<?php
// 一行コメント

# これも一行コメント(あまり使われない)

/*
 複数行
 コメント
*/

/**
 * ドキュメントコメント(PHPDoc形式)
 * @param string $name 名前
 * @return void
 */

Python:

# 一行コメント

"""
複数行
コメント(ドキュメンテーション文字列としても使用される)
"""

'''
これも複数行コメント
'''

def function(name: str) -> None:
    """
    ドキュメンテーション文字列(ドックストリング)
    
    Args:
        name: 名前
    
    Returns:
        None
    """
    pass

出力

PHP:

<?php
$name = "Alice";
// 複数の方法がある
echo "Hello, $name!";  // 変数展開あり

Python:

name = "Alice"
# こちらも複数の方法がある
print(f"Hello, {name}!")  # f文字列(Python 3.6以降)

PHP:

echo 'Hello, ' . $name . '!';  // 結合演算子

Python:

print("Hello, " + name + "!")  # 結合演算子

PHP:

print("Hello, $name!");  // 関数形式

Python:

print("Hello, {}!".format(name))  # format関数

PHP:

printf("Hello, %s!", $name);  // フォーマット指定

Python:

print("Hello, %s!" % name)  # C言語形式(非推奨)

PHP:

var_dump($name);  // デバッグ情報

Python:

print(name)  # 単純な出力

制御構文

条件分岐

PHP:

<?php
$score = 85;

// if-elseif-else
if ($score >= 90) {
    echo "A";
} elseif ($score >= 80) {
    echo "B";
} elseif ($score >= 70) {
    echo "C";
} else {
    echo "D";
}

Python:

score = 85

# if-elif-else
if score >= 90:
    print("A")
elif score >= 80:
    print("B")
elif score >= 70:
    print("C")
else:
    print("D")

PHP:

// 三項演算子
$result = ($score >= 60) ? "合格" : "不合格";

Python:

# 三項演算子に相当する式
result = "合格" if score >= 60 else "不合格"

PHP:

// switch文
switch ($score) {
    case 100:
        echo "満点";
        break;
    case 0:
        echo "零点";
        break;
    default:
        echo "その他";
        break;
}

Python:

# Pythonにはswitch文がないが、Python 3.10からマッチング文が導入
# Python 3.10以降
match score:
    case 100:
        print("満点")
    case 0:
        print("零点")
    case _:
        print("その他")

PHP:

// PHP 8のマッチ式
$grade = match (true) {
    $score >= 90 => "A",
    $score >= 80 => "B",
    $score >= 70 => "C",
    default => "D",
};

Python:

# 従来のPythonではdictを使ったディスパッチも一般的
grade_map = {
    range(90, 101): "A",
    range(80, 90): "B",
    range(70, 80): "C",
    range(0, 70): "D"
}
grade = next((v for k, v in grade_map.items() if score in k), "Invalid")

ループ

PHP:

<?php
// for
for ($i = 0; $i < 5; $i++) {
    echo $i;
}

Python:

# for(Pythonのforは常に反復可能オブジェクトを使う)
for i in range(5):
    print(i)

PHP:

// while
$j = 0;
while ($j < 5) {
    echo $j;
    $j++;
}

Python:

# while
j = 0
while j < 5:
    print(j)
    j += 1

PHP:

// do-while
$k = 0;
do {
    echo $k;
    $k++;
} while ($k < 5);

Python:

# Pythonにはdo-whileがないので模倣する
k = 0
while True:
    print(k)
    k += 1
    if k >= 5:
        break

PHP:

// foreach(配列)
$colors = ["red", "green", "blue"];
foreach ($colors as $color) {
    echo $color;
}

Python:

# リストのループ
colors = ["red", "green", "blue"]
for color in colors:
    print(color)

PHP:

// foreach(連想配列)
$person = ["name" => "John", "age" => 30];
foreach ($person as $key => $value) {
    echo "$key: $value";
}

Python:

# 辞書のループ
person = {"name": "John", "age": 30}
for key, value in person.items():
    print(f"{key}: {value}")

PHP:

// インデックス付きループ(少し冗長)
$colors = ["red", "green", "blue"];
for ($i = 0; $i < count($colors); $i++) {
    echo "$i: {$colors[$i]}";
}

Python:

# enumerate関数でインデックス付きループ
for index, color in enumerate(colors):
    print(f"{index}: {color}")

ループ制御

PHP:

<?php
for ($i = 0; $i < 10; $i++) {
    if ($i == 5) {
        break;  // ループを抜ける
    }
    if ($i % 2 == 0) {
        continue;  // 次の反復へ
    }
    echo $i;  // 1, 3, 7, 9が出力される
}

Python:

for i in range(10):
    if i == 5:
        break  # ループを抜ける
    if i % 2 == 0:
        continue  # 次の反復へ
    print(i)  # 1, 3, 7, 9が出力される

オブジェクト指向プログラミング

クラス定義と継承

PHP:

<?php
// クラス定義
class Person {
    // プロパティ(PHP 7.4以降で型宣言可能)
    private string $name;
    protected int $age;
    public bool $isActive = true;
    
    // コンストラクタ
    public function __construct(string $name, int $age = 0) {
        $this->name = $name;
        $this->age = $age;
    }
    
    // メソッド
    public function greet(): string {
        return "Hello, I'm {$this->name}";
    }
    
    // ゲッター
    public function getName(): string {
        return $this->name;
    }
    
    // セッター
    public function setName(string $name): void {
        $this->name = $name;
    }
}

Python:

# クラス定義
class Person:
    # クラス変数
    species = "Human"
    
    # コンストラクタ
    def __init__(self, name: str, age: int = 0):
        # インスタンス変数
        self.name = name  # publicに相当
        self._age = age   # protectedの慣習(実際は普通にアクセス可能)
        self.__active = True  # privateに相当(名前修飾により隠蔽)
    
    # メソッド
    def greet(self) -> str:
        return f"Hello, I'm {self.name}"
    
    # プロパティゲッター
    @property
    def age(self) -> int:
        return self._age
    
    # プロパティセッター
    @age.setter
    def age(self, value: int) -> None:
        if value >= 0:
            self._age = value

PHP:

// 継承
class Employee extends Person {
    private string $position;
    
    public function __construct(string $name, int $age, string $position) {
        parent::__construct($name, $age);
        $this->position = $position;
    }
    
    // オーバーライド
    public function greet(): string {
        return parent::greet() . " and I work as a {$this->position}";
    }
}

Python:

# 継承
class Employee(Person):
    def __init__(self, name: str, age: int, position: str):
        super().__init__(name, age)  # 親クラスのコンストラクタを呼び出し
        self.position = position
    
    # オーバーライド
    def greet(self) -> str:
        return super().greet() + f" and I work as a {self.position}"

PHP:

// 使用例
$person = new Person("John", 30);
echo $person->greet();  // "Hello, I'm John"

$employee = new Employee("Alice", 25, "Developer");
echo $employee->greet();  // "Hello, I'm Alice and I work as a Developer"

Python:

# 使用例
person = Person("John", 30)
print(person.greet())  # "Hello, I'm John"

employee = Employee("Alice", 25, "Developer")
print(employee.greet())  # "Hello, I'm Alice and I work as a Developer"

抽象クラスとインターフェース

PHP:

<?php
// 抽象クラス
abstract class Vehicle {
    protected string $brand;
    
    public function __construct(string $brand) {
        $this->brand = $brand;
    }
    
    // 抽象メソッド
    abstract public function move(): string;
    
    // 具象メソッド
    public function getBrand(): string {
        return $this->brand;
    }
}

Python:

from abc import ABC, abstractmethod

# 抽象基底クラス
class Vehicle(ABC):
    def __init__(self, brand: str):
        self._brand = brand
    
    # 抽象メソッド
    @abstractmethod
    def move(self) -> str:
        pass
    
    # 具象メソッド
    def get_brand(self) -> str:
        return self._brand

PHP:

// インターフェース
interface Chargeable {
    public function charge(): void;
    public function getBatteryLevel(): int;
}

Python:

# Pythonはマルチ継承を使ってインターフェースを模倣
class Chargeable(ABC):
    @abstractmethod
    def charge(self) -> None:
        pass
    
    @abstractmethod
    def get_battery_level(self) -> int:
        pass

PHP:

// 抽象クラスとインターフェースを実装
class ElectricCar extends Vehicle implements Chargeable {
    private int $batteryLevel = 0;
    
    public function move(): string {
        return "Electric car {$this->brand} is moving silently";
    }
    
    public function charge(): void {
        $this->batteryLevel = 100;
    }
    
    public function getBatteryLevel(): int {
        return $this->batteryLevel;
    }
}

Python:

# 抽象クラスとインターフェース相当を実装
class ElectricCar(Vehicle, Chargeable):
    def __init__(self, brand: str):
        super().__init__(brand)
        self._battery_level = 0
    
    def move(self) -> str:
        return f"Electric car {self._brand} is moving silently"
    
    def charge(self) -> None:
        self._battery_level = 100
    
    def get_battery_level(self) -> int:
        return self._battery_level

PHP:

// 使用例
$tesla = new ElectricCar("Tesla");
echo $tesla->move();
$tesla->charge();
echo $tesla->getBatteryLevel();  // 100

Python:

# 使用例
tesla = ElectricCar("Tesla")
print(tesla.move())
tesla.charge()
print(tesla.get_battery_level())  # 100

トレイト/ミックスイン

PHP:

<?php
// トレイト
trait Loggable {
    private array $logs = [];
    
    public function log(string $message): void {
        $this->logs[] = date('Y-m-d H:i:s') . ": $message";
    }
    
    public function getLogs(): array {
        return $this->logs;
    }
}

Python:

from datetime import datetime

# ミックスイン(Pythonではマルチ継承で実現)
class LoggableMixin:
    def __init__(self):
        self._logs = []
    
    def log(self, message: str) -> None:
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self._logs.append(f"{timestamp}: {message}")
    
    def get_logs(self) -> list:
        return self._logs

PHP:

trait Serializable {
    public function toJson(): string {
        return json_encode(get_object_vars($this));
    }
}

Python:

import json

class SerializableMixin:
    def to_json(self) -> str:
        return json.dumps(self.__dict__)

PHP:

// トレイトを使用するクラス
class User {
    use Loggable, Serializable;
    
    private string $name;
    private string $email;
    
    public function __construct(string $name, string $email) {
        $this->name = $name;
        $this->email = $email;
        $this->log("User created");
    }
}

Python:

# ミックスインを使用するクラス
class User(LoggableMixin, SerializableMixin):
    def __init__(self, name: str, email: str):
        LoggableMixin.__init__(self)  # 明示的に初期化
        self._name = name
        self._email = email
        self.log("User created")

PHP:

// 使用例
$user = new User("John", "john@example.com");
$user->log("Profile updated");
print_r($user->getLogs());
echo $user->toJson();

Python:

# 使用例
user = User("John", "john@example.com")
user.log("Profile updated")
print(user.get_logs())
print(user.to_json())

名前空間

PHP:

<?php
// ファイル: App/Models/User.php
namespace App\Models;

class User {
    private string $name;
    
    public function __construct(string $name) {
        $this->name = $name;
    }
}

Python:

# ファイル: app/models/user.py
class User:
    def __init__(self, name: str):
        self.name = name

PHP:

// ファイル: App/Controllers/UserController.php
namespace App\Controllers;

use App\Models\User;
use App\Services\Logger as LogService;

class UserController {
    public function createUser(string $name): User {
        $logger = new LogService();
        $logger->log("Creating user: $name");
        return new User($name);
    }
}

Python:

# ファイル: app/controllers/user_controller.py
from app.models.user import User
from app.services.logger import Logger as LogService

class UserController:
    def create_user(self, name: str) -> User:
        logger = LogService()
        logger.log(f"Creating user: {name}")
        return User(name)

注意: Pythonのパッケージシステムでは、各ディレクトリに __init__.py ファイルを作成する必要があります。

例外処理

基本的な例外処理

PHP:

<?php
function divide($a, $b) {
    if ($b === 0) {
        throw new InvalidArgumentException("Division by zero");
    }
    return $a / $b;
}

Python:

def divide(a, b):
    if b == 0:
        raise ValueError("Division by zero")
    return a / b

PHP:

// 例外をキャッチする
try {
    echo divide(10, 2);  // 5
    echo divide(10, 0);  // 例外発生
} catch (InvalidArgumentException $e) {
    echo "エラー: " . $e->getMessage();  // "エラー: Division by zero"
} catch (Exception $e) {
    echo "その他のエラー: " . $e->getMessage();
} finally {
    echo "処理完了";  // 常に実行される
}

Python:

# 例外をキャッチする
try:
    print(divide(10, 2))  # 5.0
    print(divide(10, 0))  # 例外発生
except ValueError as e:
    print(f"エラー: {e}")  # "エラー: Division by zero"
except Exception as e:
    print(f"その他のエラー: {e}")
finally:
    print("処理完了")  # 常に実行される

カスタム例外

PHP:

<?php
// カスタム例外クラス
class FileNotFoundException extends Exception {
    public function __construct(string $path, int $code = 0, Exception $previous = null) {
        $message = "File not found: $path";
        parent::__construct($message, $code, $previous);
    }
}

Python:

# カスタム例外クラス
class FileNotFoundException(Exception):
    def __init__(self, path, *args, **kwargs):
        self.path = path
        message = f"File not found: {path}"
        super().__init__(message, *args, **kwargs)

PHP:

function readFile(string $path) {
    if (!file_exists($path)) {
        throw new FileNotFoundException($path);
    }
    return file_get_contents($path);
}

Python:

def read_file(path):
    import os
    if not os.path.exists(path):
        raise FileNotFoundException(path)
    with open(path, 'r') as f:
        return f.read()

PHP:

try {
    $content = readFile("non_existent_file.txt");
} catch (FileNotFoundException $e) {
    echo $e->getMessage();
} catch (Exception $e) {
    echo "Unexpected error: " . $e->getMessage();
}

Python:

try:
    content = read_file("non_existent_file.txt")
except FileNotFoundException as e:
    print(e)
except Exception as e:
    print(f"Unexpected error: {e}")

文字列処理

基本的な文字列操作

PHP:

<?php
// 文字列の連結
$first = "Hello";
$last = "World";
$message = $first . ", " . $last . "!";  // "Hello, World!"

Python:

# 文字列の連結
first = "Hello"
last = "World"
message = first + ", " + last + "!"  # "Hello, World!"
# f文字列を使った連結(Python 3.6以降)
message = f"{first}, {last}!"  # "Hello, World!"

PHP:

// 変数の展開
$name = "Alice";
$greeting = "Hello, $name!";  // "Hello, Alice!"
$greeting2 = 'Hello, ' . $name . '!';  // "Hello, Alice!"

Python:

# 変数の展開
name = "Alice"
greeting = f"Hello, {name}!"  # "Hello, Alice!" (Python 3.6+)
greeting2 = "Hello, {}!".format(name)  # "Hello, Alice!"

PHP:

// 文字列の長さ
$str = "こんにちは";
$length = strlen($str);  // バイト長(マルチバイト文字に非対応)
$length_mb = mb_strlen($str);  // 文字数(マルチバイト対応)

Python:

# 文字列の長さ(Pythonは常にUnicodeで文字数をカウント)
str_value = "こんにちは"
length = len(str_value)  # 5

PHP:

// 部分文字列
$substr = substr("Hello, World!", 0, 5);  // "Hello"
$substr_mb = mb_substr("こんにちは", 0, 2);  // "こん"

Python:

# 部分文字列(スライス)
substr = "Hello, World!"[0:5]  # "Hello"
substr2 = "こんにちは"[0:2]  # "こん"

PHP:

// 文字列の検索
$pos = strpos("Hello, World!", "World");  // 7
$pos_mb = mb_strpos("こんにちは世界", "世界");  // 5

Python:

# 文字列の検索
pos = "Hello, World!".find("World")  # 7
pos2 = "こんにちは世界".find("世界")  # 5

PHP:

// 文字列の置換
$replaced = str_replace("World", "PHP", "Hello, World!");  // "Hello, PHP!"

Python:

# 文字列の置換
replaced = "Hello, World!".replace("World", "Python")  # "Hello, Python!"

PHP:

// 大文字・小文字変換
$upper = strtoupper("hello");  // "HELLO"
$lower = strtolower("HELLO");  // "hello"

Python:

# 大文字・小文字変換
upper = "hello".upper()  # "HELLO"
lower = "HELLO".lower()  # "hello"

文字列分割と結合

PHP:

<?php
// 文字列を配列に分割
$parts = explode(",", "apple,banana,orange");
// ["apple", "banana", "orange"]

Python:

# 文字列を配列に分割
parts = "apple,banana,orange".split(",")
# ["apple", "banana", "orange"]

PHP:

// 配列を文字列に結合
$fruits = ["apple", "banana", "orange"];
$csv = implode(",", $fruits);  // "apple,banana,orange"

Python:

# 配列を文字列に結合
fruits = ["apple", "banana", "orange"]
csv = ",".join(fruits)  # "apple,banana,orange"

PHP:

// 正規表現による分割
$words = preg_split("/\s+/", "Hello  World   Test");
// ["Hello", "World", "Test"]

Python:

# 正規表現による分割
import re
words = re.split(r"\s+", "Hello  World   Test")
# ["Hello", "World", "Test"]

文字列のフォーマット

PHP:

<?php
$name = "John";
$age = 30;

// sprintf/printf
$formatted = sprintf("Name: %s, Age: %d", $name, $age);
printf("Name: %s, Age: %d", $name, $age);  // 出力する

Python:

name = "John"
age = 30

# format関数
formatted = "Name: {}, Age: {}".format(name, age)
# f文字列(Python 3.6以降)
formatted = f"Name: {name}, Age: {age}"

PHP:

// 文字列補間
$formatted = "Name: $name, Age: $age";

Python:

# %演算子(古い方法)
formatted = "Name: %s, Age: %d" % (name, age)

PHP:

// number_format
$price = number_format(1234.56, 2);  // "1,234.56"

Python:

# 数値のフォーマット
price = "{:,.2f}".format(1234.56)  # "1,234.56"
# f文字列での数値フォーマット
price = f"{1234.56:,.2f}"  # "1,234.56"

PHP:

// パディング
$padded = str_pad("Hello", 10, "-", STR_PAD_RIGHT);  // "Hello-----"

Python:

# パディング
padded = "Hello".ljust(10, "-")  # "Hello-----"
padded2 = f"{'Hello':<10}"  # "Hello     "(スペースで埋める)

配列と連想配列

配列の基本操作

PHP:

<?php
// 配列の作成
$fruits = ["apple", "banana", "orange"];
$numbers = array(1, 2, 3, 4, 5);

Python:

# リストの作成
fruits = ["apple", "banana", "orange"]
numbers = [1, 2, 3, 4, 5]

PHP:

// 要素へのアクセス
echo $fruits[0];  // "apple"
$fruits[1] = "grape";  // 更新

Python:

# 要素へのアクセス
print(fruits[0])  # "apple"
fruits[1] = "grape"  # 更新

PHP:

// 配列の末尾に追加
$fruits[] = "kiwi";  // ["apple", "grape", "orange", "kiwi"]
array_push($fruits, "melon");  // ["apple", "grape", "orange", "kiwi", "melon"]

Python:

# リストの末尾に追加
fruits.append("kiwi")  # ["apple", "grape", "orange", "kiwi"]

PHP:

// 配列の先頭に追加
array_unshift($fruits, "pear");  // ["pear", "apple", "grape", "orange", "kiwi", "melon"]

Python:

# リストの先頭に追加
fruits.insert(0, "pear")  # ["pear", "apple", "grape", "orange", "kiwi"]

PHP:

// 配列の末尾から削除
$last = array_pop($fruits);  // "melon"

Python:

# リストの末尾から削除
last = fruits.pop()  # "kiwi"

PHP:

// 配列の先頭から削除
$first = array_shift($fruits);  // "pear"

Python:

# リストの先頭から削除
first = fruits.pop(0)  # "pear"

PHP:

// 配列の結合
$more_fruits = ["cherry", "peach"];
$all_fruits = array_merge($fruits, $more_fruits);

Python:

# リストの結合
more_fruits = ["cherry", "peach"]
all_fruits = fruits + more_fruits
# または
fruits.extend(more_fruits)

PHP:

// 配列のサイズ
$count = count($fruits);

Python:

# リストのサイズ
count = len(fruits)

PHP:

// 配列のソート
sort($fruits);  // アルファベット順
rsort($fruits);  // 逆順

Python:

# リストのソート
fruits.sort()  # アルファベット順
fruits.sort(reverse=True)  # 逆順

連想配列/辞書

PHP:

<?php
// 連想配列の作成
$person = [
    "name" => "John",
    "age" => 30,
    "city" => "New York"
];

// 別の構文
$person = array(
    "name" => "John",
    "age" => 30,
    "city" => "New York"
);

Python:

# 辞書の作成
person = {
    "name": "John",
    "age": 30,
    "city": "New York"
}

PHP:

// 要素へのアクセス
echo $person["name"];  // "John"
$person["age"] = 31;  // 更新

Python:

# 要素へのアクセス
print(person["name"])  # "John"
person["age"] = 31  # 更新

# 要素へのアクセス(キーが存在しない場合にエラーを避ける)
name = person.get("name")  # "John"
phone = person.get("phone")  # None
phone = person.get("phone", "Not available")  # デフォルト値を提供

PHP:

// 要素の追加
$person["email"] = "john@example.com";

Python:

# 要素の追加
person["email"] = "john@example.com"

PHP:

// 要素の削除
unset($person["city"]);

Python:

# 要素の削除
del person["city"]
# または
city = person.pop("city", None)  # キーが存在しない場合はNoneを返す

PHP:

// キーの存在確認
$exists = array_key_exists("name", $person);  // true
$isset = isset($person["phone"]);  // false

Python:

# キーの存在確認
exists = "name" in person  # True

PHP:

// キーと値の取得
$keys = array_keys($person);  // ["name", "age", "email"]
$values = array_values($person);  // ["John", 31, "john@example.com"]

Python:

# キーと値の取得
keys = list(person.keys())  # ["name", "age", "email"]
values = list(person.values())  # ["John", 31, "john@example.com"]

PHP:

// 連想配列のループ
foreach ($person as $key => $value) {
    echo "$key: $value\n";
}

Python:

# 辞書のループ
for key, value in person.items():
    print(f"{key}: {value}")

リスト内包表記(Pythonの特徴)

PHP:

<?php
// PHPにはリスト内包表記に相当する機能はないが、array_mapで近い処理ができる
$numbers = [1, 2, 3, 4, 5];
$squares = array_map(function($n) { return $n * $n; }, $numbers);
// [1, 4, 9, 16, 25]

Python:

numbers = [1, 2, 3, 4, 5]

# リスト内包表記
squares = [n * n for n in numbers]
# [1, 4, 9, 16, 25]

PHP:

// フィルタリング
$evens = array_filter($numbers, function($n) { return $n % 2 == 0; });
// [2, 4]

Python:

# 条件付きリスト内包表記
evens = [n for n in numbers if n % 2 == 0]
# [2, 4]

PHP:

// 組み合わせ
$squared_evens = array_map(
    function($n) { return $n * $n; },
    array_filter($numbers, function($n) { return $n % 2 == 0; })
);
// [4, 16]

Python:

# 複合的なリスト内包表記
squared_evens = [n * n for n in numbers if n % 2 == 0]
# [4, 16]

# 辞書内包表記
squares_dict = {n: n * n for n in numbers}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

日付と時間の操作

基本的な日付と時間

PHP:

<?php
// 現在の時刻(UNIXタイムスタンプ)
$now = time();  // 例:1640995200(秒単位)

Python:

import time
from datetime import datetime, timedelta

# 現在の時刻(UNIXタイムスタンプ)
now = time.time()  # 例:1640995200.0(浮動小数点、秒単位)

PHP:

// タイムスタンプからフォーマット
$date_string = date("Y-m-d H:i:s", $now);  // "2022-01-01 12:00:00"

Python:

# 現在の日時(datetimeオブジェクト)
dt_now = datetime.now()  # 2022-01-01 12:00:00.000000

# タイムスタンプからフォーマット
date_string = datetime.fromtimestamp(now).strftime("%Y-%m-%d %H:%M:%S")
# "2022-01-01 12:00:00"

PHP:

// 文字列からタイムスタンプ
$timestamp = strtotime("2022-01-01 12:00:00");  // 1640995200

Python:

# 文字列からdatetimeオブジェクト
dt = datetime.strptime("2022-01-01 12:00:00", "%Y-%m-%d %H:%M:%S")

# datetimeオブジェクトからタイムスタンプ
timestamp = dt.timestamp()  # 1640995200.0

PHP:

// 3日後のタイムスタンプ
$three_days_later = strtotime("+3 days");

Python:

# 3日後の日時
three_days_later = dt_now + timedelta(days=3)

PHP:

// 日付の比較
$is_future = $timestamp > time();  // 過去の日付なのでfalse

Python:

# 日付の比較
is_future = dt > datetime.now()  # 過去の日付なのでFalse

DateTimeクラス/オブジェクト

PHP:

<?php
// DateTimeオブジェクトの作成
$now = new DateTime();  // 現在時刻
$date = new DateTime("2022-01-01 12:00:00");  // 特定の時刻
$timestamp_date = new DateTime("@" . time());  // タイムスタンプから

Python:

from datetime import datetime, timedelta, timezone
import pytz  # タイムゾーン操作に便利なライブラリ

# datetimeオブジェクトの作成
now = datetime.now()  # 現在時刻
date = datetime(2022, 1, 1, 12, 0, 0)  # 特定の時刻
timestamp_date = datetime.fromtimestamp(time.time())  # タイムスタンプから

PHP:

// タイムゾーン設定
$tokyo = new DateTime("now", new DateTimeZone("Asia/Tokyo"));

Python:

# タイムゾーン設定
tokyo = datetime.now(pytz.timezone("Asia/Tokyo"))

PHP:

// フォーマット
$formatted = $date->format("Y年m月d日 H時i分s秒");

Python:

# フォーマット
formatted = date.strftime("%Y年%m月%d日 %H時%M分%S秒")

PHP:

// 日時の操作
$date->modify("+1 month");  // 1ヶ月後
$date->add(new DateInterval("P1Y2M"));  // 1年2ヶ月後
$date->sub(new DateInterval("P10D"));  // 10日前

Python:

# 日時の操作
one_month_later = date.replace(month=date.month + 1)  # 月を直接指定
one_year_two_months_later = date.replace(
    year=date.year + 1,
    month=date.month + 2 if date.month < 11 else (date.month + 2) % 12
)
ten_days_ago = date - timedelta(days=10)

PHP:

// 日付間の差
$diff = $now->diff($date);
echo $diff->format("%y年%m月%d日の差");

Python:

# 日付間の差
diff = now - date
print(f"{diff.days}日の差")  # より複雑な差分計算には追加の処理が必要

PHP:

// 日付の比較
$is_before = $date < $now;

Python:

# 日付の比較
is_before = date < now

ファイル操作

基本的なファイル操作

PHP:

<?php
// ファイルの読み込み(全体)
$content = file_get_contents("example.txt");

Python:

# ファイルの読み込み(全体)
with open("example.txt", "r", encoding="utf-8") as f:
    content = f.read()

PHP:

// ファイルに書き込み
file_put_contents("output.txt", "Hello, World!", FILE_APPEND);  // 追記

Python:

# ファイルに書き込み
with open("output.txt", "w", encoding="utf-8") as f:
    f.write("Hello, World!")

# 追記モード
with open("output.txt", "a", encoding="utf-8") as f:
    f.write("追加のテキスト")

PHP:

// ファイルを行単位で読み込み
$lines = file("example.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
    echo $line;
}

Python:

# ファイルを行単位で読み込み
with open("example.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
# または
with open("example.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

PHP:

// ファイルの存在確認
if (file_exists("example.txt")) {
    echo "ファイルが存在します";
}

Python:

# ファイルの存在確認
import os
if os.path.exists("example.txt"):
    print("ファイルが存在します")

PHP:

// ファイルの削除
unlink("temporary.txt");

Python:

# ファイルの削除
import os
os.remove("temporary.txt")

PHP:

// ファイルのコピー
copy("source.txt", "destination.txt");

Python:

# ファイルのコピー
import shutil
shutil.copy("source.txt", "destination.txt")

PHP:

// ファイルの移動/名前変更
rename("old.txt", "new.txt");

Python:

# ファイルの移動/名前変更
import os
os.rename("old.txt", "new.txt")

ディレクトリ操作

PHP:

<?php
// ディレクトリの作成
mkdir("new_folder", 0755);

Python:

import os
import shutil
import glob

# ディレクトリの作成
os.mkdir("new_folder")

PHP:

// 再帰的にディレクトリを作成
mkdir("path/to/new/folder", 0755, true);

Python:

# 再帰的にディレクトリを作成
os.makedirs("path/to/new/folder", exist_ok=True)

PHP:

// ディレクトリ内のファイル一覧
$files = scandir("folder");

Python:

# ディレクトリ内のファイル一覧
files = os.listdir("folder")

PHP:

// 特定パターンのファイルを検索
$php_files = glob("*.php");

Python:

# 特定パターンのファイルを検索
py_files = glob.glob("*.py")

PHP:

// ディレクトリの削除
rmdir("empty_folder");  // 空のディレクトリのみ削除可能

Python:

# ディレクトリの削除
os.rmdir("empty_folder")  # 空のディレクトリのみ削除可能

PHP:

// ディレクトリとその中身を再帰的に削除するには専用関数が必要
function rmdir_recursive($dir) {
    $files = array_diff(scandir($dir), array('.','..'));
    foreach ($files as $file) {
        $path = "$dir/$file";
        is_dir($path) ? rmdir_recursive($path) : unlink($path);
    }
    return rmdir($dir);
}

Python:

# ディレクトリとその中身を再帰的に削除
shutil.rmtree("folder")  # 注意: 取り消せない操作

正規表現

パターンマッチング

PHP:

<?php
// 正規表現でマッチング
$text = "Email: example@example.com";
$pattern = '/[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}/i';

if (preg_match($pattern, $text, $matches)) {
    echo "マッチしました: " . $matches[0];  // "example@example.com"
}

Python:

import re

# 正規表現でマッチング
text = "Email: example@example.com"
pattern = r'[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}'

match = re.search(pattern, text, re.IGNORECASE)
if match:
    print(f"マッチしました: {match.group(0)}")  # "example@example.com"

PHP:

// すべてのマッチを取得
$text = "Contact us at info@example.com or support@example.org";
preg_match_all($pattern, $text, $matches);
print_r($matches[0]);  // ["info@example.com", "support@example.org"]

Python:

# すべてのマッチを取得
text = "Contact us at info@example.com or support@example.org"
matches = re.findall(pattern, text, re.IGNORECASE)
print(matches)  # ["info@example.com", "support@example.org"]

PHP:

// 正規表現による置換
$replaced = preg_replace($pattern, "[EMAIL]", $text);
// "Contact us at [EMAIL] or [EMAIL]"

Python:

# 正規表現による置換
replaced = re.sub(pattern, "[EMAIL]", text, flags=re.IGNORECASE)
# "Contact us at [EMAIL] or [EMAIL]"

PHP:

// 複雑な置換(コールバック関数を使用)
$result = preg_replace_callback(
    $pattern,
    function ($match) {
        return strtoupper($match[0]);
    },
    $text
);
// "Contact us at INFO@EXAMPLE.COM or SUPPORT@EXAMPLE.ORG"

Python:

# 複雑な置換(関数を使用)
def upper_email(match):
    return match.group(0).upper()

result = re.sub(pattern, upper_email, text, flags=re.IGNORECASE)
# "Contact us at INFO@EXAMPLE.COM or SUPPORT@EXAMPLE.ORG"

よく使う便利機能

配列操作

PHP:

<?php
$numbers = [1, 2, 3, 4, 5];

// map: 各要素に処理を適用
$doubled = array_map(function($n) { return $n * 2; }, $numbers);
// [2, 4, 6, 8, 10]

Python:

numbers = [1, 2, 3, 4, 5]

# map: 各要素に処理を適用
doubled = list(map(lambda n: n * 2, numbers))
# または
doubled = [n * 2 for n in numbers]
# [2, 4, 6, 8, 10]

PHP:

// filter: 条件に合う要素のみ抽出
$evens = array_filter($numbers, function($n) { return $n % 2 == 0; });
// [2, 4]

Python:

# filter: 条件に合う要素のみ抽出
evens = list(filter(lambda n: n % 2 == 0, numbers))
# または
evens = [n for n in numbers if n % 2 == 0]
# [2, 4]

PHP:

// reduce: 要素を集約
$sum = array_reduce($numbers, function($carry, $n) { return $carry + $n; }, 0);
// 15

Python:

# reduce: 要素を集約
from functools import reduce
sum_value = reduce(lambda x, y: x + y, numbers, 0)
# または単にPythonの組み込み関数
sum_value = sum(numbers)
# 15

PHP:

// 配列からキーと値のペアを取得
$fruits = ["apple" => "red", "banana" => "yellow"];
foreach ($fruits as $name => $color) {
    echo "$name is $color";
}

Python:

# 辞書からキーと値のペアを取得
fruits = {"apple": "red", "banana": "yellow"}
for name, color in fruits.items():
    print(f"{name} is {color}")

JSON処理

PHP:

<?php
// 配列/オブジェクトをJSONに変換
$data = ["name" => "John", "age" => 30];
$json = json_encode($data);
// {"name":"John","age":30}

Python:

import json

# 辞書をJSONに変換
data = {"name": "John", "age": 30}
json_str = json.dumps(data)
# {"name": "John", "age": 30}

PHP:

// 整形したJSON
$json_pretty = json_encode($data, JSON_PRETTY_PRINT);

Python:

# 整形したJSON
json_pretty = json.dumps(data, indent=4)

PHP:

// JSONを配列/オブジェクトに変換
$decoded = json_decode($json, true);  // 連想配列として
$object = json_decode($json);  // オブジェクトとして

Python:

# JSONを辞書に変換
decoded = json.loads(json_str)

ランダム値の生成

PHP:

<?php
// 乱数生成
$random = rand(1, 100);  // 1から100までの整数

Python:

import random
import string

# 乱数生成
random_num = random.randint(1, 100)  # 1から100までの整数

PHP:

// PHP 7以降の安全な乱数
$secure_random = random_int(1, 100);

Python:

# Pythonの標準randintは既に暗号論的に十分な乱数ではない
# 暗号論的に安全な乱数が必要な場合は secrets モジュールを使用
import secrets
secure_random = secrets.randbelow(100) + 1  # 1から100までの整数

PHP:

// 配列からランダムに要素を選択
$fruits = ["apple", "banana", "orange"];
$random_fruit = $fruits[array_rand($fruits)];

Python:

# 配列からランダムに要素を選択
fruits = ["apple", "banana", "orange"]
random_fruit = random.choice(fruits)

PHP:

// ランダムな文字列生成
function generate_random_string($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $random_string = '';
    for ($i = 0; $i < $length; $i++) {
        $random_string .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $random_string;
}

Python:

# ランダムな文字列生成
def generate_random_string(length=10):
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))

暗号化とハッシュ

PHP:

<?php
// パスワードのハッシュ化(推奨方法)
$password = "secret123";
$hash = password_hash($password, PASSWORD_DEFAULT);

Python:

import hashlib
import os
import binascii
import bcrypt  # 外部ライブラリ

# パスワードのハッシュ化(bcryptを使用)
password = "secret123"
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password.encode(), salt)

PHP:

// ハッシュの検証
$is_valid = password_verify($password, $hash);  // true

Python:

# ハッシュの検証
is_valid = bcrypt.checkpw(password.encode(), hashed)  # True

PHP:

// MD5ハッシュ(非推奨)
$md5 = md5($password);

Python:

# MD5ハッシュ(非推奨)
md5 = hashlib.md5(password.encode()).hexdigest()

PHP:

// SHA-256ハッシュ
$sha256 = hash('sha256', $password);

Python:

# SHA-256ハッシュ
sha256 = hashlib.sha256(password.encode()).hexdigest()

PHP:

// ランダムなバイト列を生成
$bytes = random_bytes(16);
$hex = bin2hex($bytes);

Python:

# ランダムなバイト列を生成
bytes_val = os.urandom(16)
hex_val = binascii.hexlify(bytes_val).decode()

デバッグ情報の出力

PHP:

<?php
// 変数の詳細情報を出力
$data = ["name" => "John", "age" => 30];
var_dump($data);

Python:

# 変数の詳細情報を出力
data = {"name": "John", "age": 30}
print(data)

PHP:

// 読みやすい形式で出力
print_r($data);

Python:

# 詳細な情報表示
import pprint
pprint.pprint(data)

PHP:

// 変数の型と値を取得
$type = gettype($data);  // "array"
$is_array = is_array($data);  // true

Python:

# 変数の型を取得
type_val = type(data)  # <class 'dict'>
is_dict = isinstance(data, dict)  # True

PHP:

// バックトレース情報
debug_print_backtrace();
$trace = debug_backtrace();

Python:

# スタックトレース情報
import traceback
traceback.print_stack()
stack = traceback.format_stack()

まとめ

PHPとPythonは構文面では多くの違いがありますが、根底にある概念は比較的類似しています。しかし、設計思想や実行環境の違いにより、ベストプラクティスや一般的なパターンには注意すべき違いがあります。

PHPからPythonに移行する際の主なポイント:

  1. 構文の違い: 変数の接頭辞 ($) の有無、ブロックの区切り方(波括弧 vs インデント)
  2. 命名規則: PHP(camelCase/PascalCase)vs Python(snake_case)
  3. 配列と辞書: PHPの配列は多目的(順序付き配列と連想配列の両方)、Pythonではリストと辞書に分かれている
  4. クラスとオブジェクト指向: どちらも強力なOOP機能を提供しているが、アクセス修飾子やトレイト/ミックスインの扱いに違いがある
  5. 文字列操作: PHPのマルチバイト対応関数(mb_*)vs Pythonの標準Unicode対応
  6. Python固有の機能: リスト内包表記、ジェネレータ、デコレータなど

どちらの言語も幅広い用途に適していますが、パフォーマンス特性や使用環境によって、それぞれの得意分野があります。PHPはWebアプリケーション開発に特化している一方、Pythonはデータ分析、機械学習、自動化スクリプトなど、より幅広い領域で活用されています。

両方の言語を学ぶことで、問題解決のアプローチの幅が広がり、より強力なツールセットを身につけることができます。

参考リソース

Discussion