Open10

Python 文法

shun sakaishun sakai

with の中で定義した変数はその中を出ても有効

# Online Python Playground
# Use the online IDE to write, edit & run your Python code
# Create, edit & delete files online

class Resource:
    def __enter__(self):
        self.resource = "hoge"
        print(self.resource)
        return self.resource

    def __exit__(self, exc_type, exc_value, traceback):
        print("Resource is now closed")

# Resourceクラスを使用してwithステートメントのスコープをテスト
with Resource() as res:
    print("res in with: ", res)
    test = "test"
    print("test in with: ", test)

print("res in main: ", res)  # withブロック外でaが存在するかを確認
print("test in main: ", test)

shun sakaishun sakai

一方、メソッドの場合は、メソッドを出るとアクセスできなくなる。

def hoge():
    a = 'a'
    print("a in hoge method: ", a)

hoge()
print(a)

shun sakaishun sakai
def gen_function(n):
    print('start')
    while n:
        print(f'yield: {n}')
        yield n
        print("after n")
        n -= 1

# for i in gen_function(2):
#     print(i)


gen = gen_function(3)
next(gen)
next(gen)
next(gen)
# Output
# ```
# start
# yield: 3
# after n
# yield: 2
# after n
# yield: 1
# ```

# next(gen) # File "<exec>", line 24, in <module>

print([i**2 for i in gen_function(5)]) # [25, 16, 9, 4, 1]

print(gen(5))

def reader(src):
    with open(src) as f:
        for line in f:
            yield line

def convert(line):
    return line.upper()


def writer(dest, reader):
    with open(dest, reader):
        for line in reader:
            f.write(convert(line))

writer('dest.txt', reader('src.txt'))

# 一行ずつメモリに展開されるので、大量のテキストデータでもメモリを圧迫せずに処理を行える
shun sakaishun sakai
from dataclasses import dataclass

@dataclass
class Fruit:
    name: str
    price: int = 0

apple = Fruit(name="apple", price=128)
print(apple)
print(apple.name)
apple.price = 150
print(apple.price)



class Fruit:
    def __init__(self, name, price):
        self.name = name
        self.price = price


banana = Fruit(name="banana", price=130)
print(banana)
print(banana.name)
banana.price = 160
print(banana.price)

def deco1(f):
    print("deco1 called")
    def wrapper():
        print('before exec')
        v = f()
        print('after exec')
        return v
    return wrapper

@deco1
def func():
    print('exec')
    return 1


func()


def deco2(f):
    def wrapper(*args, **kwargs):
        print('before exec')
        print("args: ", args)
        print("kwargs: ", kwargs)
        v = f(*args, **kwargs)
        print('after exec')
        return v
    return wrapper

@deco2
def func2(x, y):
    print('exec')
    return x, y

func2(1, 2)
# args:  (1, 2)
# kwargs:  {}

@deco2
def func3(a: "a", b: "b"):
    return a, b

func3(a="aa", b="bb")
# args:  ()
# kwargs:  {'a': 'aa', 'b': 'bb'}

# func3() # TypeError: func3() missing 2 required positional arguments: 'a' and 'b'

def deco3(z):
    def _deco3(f):
        def wrapper(*args, **kwargs):
            print('before exec')
            print("z: ", z)
            print("args: ", args)
            print("kwargs: ", kwargs)
            v = f(*args, **kwargs)
            print('after exec')
            return v
        return wrapper
    return _deco3

@deco3(z='z')
def func4(x, y):
    print('x, y: ', x, y)
    return x, y

func4('あ', 'い')

shun sakaishun sakai
from functools import wraps

def deco(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        print('before exec')
        v = f(*args, **kwargs)
        print('after exec')
        return v
    return wrapper

@deco
def func():
    """func です"""
    print("exec")


# @wraps(f)がない場合
print(func.__name__) # wrapper
print(func.__doc__) # None


# @wraps(f)がある場合
print(func.__name__) # func
print(func.__doc__) # func です



shun sakaishun sakai
class TextField:
    def __set_name__(self, owner, name):
        print(f'__set_name__was called')
        print(f'{owner=}, {name=}')
        self.name = name
    
    def __set__(self, instance, value):
        print('__set__ was called')
        if not isinstance(value, str):
            raise AttibuteError('must be str')
        instance.__dict__[self.name] = value
    
    def __get__(self, instance, owner):
        print('__get__ was called')
        return instance.__dict__[self.name]


class Book:
    title = TextField()

book = Book()
book.title = 'Harry Potter'

# 非データデスクリプタ
class TextField2:
    def __init__(self, value):
        if not isinstance(value, str):
            raise AttributeError('must be str')
        self.value = value

    def __set_name__(self, owner, name):
        print(f'__set_name__was called')
        print(f'{owner=}, {name=}')
        self.name = name
    
    def __get__(self, instance, owner):
        print('__get__ was called')
        return self.value
        
class Book2:
    title = TextField2('Python Book')

book = Book2()
book.title # __get__ was called
# インスタンス変数のセット
book.title = 'updated book'
print(book.title) # updated book __get__ は呼ばれない 上書きされる

shun sakaishun sakai
from collections import defaultdict

# デフォルト値がNoneのdefaultdictを作成
my_dict = defaultdict(lambda: None)

print(my_dict['non_existent_key'])
# None

my_dict2 = {}
print(my_dict2['non_existent_key'])
#   File "<exec>", line 9, in <module>
# KeyError: 'non_existent_key'
shun sakaishun sakai

TypedDict について

from typing import TypedDict

class User(TypedDict):
    name: str
    age: int

user = User(name="sakai", age=30)
print(user["name"]) # sakai

使い方

user: User = {
    "name": "Alice",
    "age": 30,
    "email": "alice@example.com"
}

型が違っていたらエラーになる。

shun sakaishun sakai

hasattr について

class MyClass:
    def __init__(self):
        self.value = 42

obj = MyClass()

# 'value'という属性がobjに存在するかどうかをチェック
print(hasattr(obj, 'value'))  # 出力: True

# 'nonexistent'という属性がobjに存在するかどうかをチェック
print(hasattr(obj, 'nonexistent'))  # 出力: False
shun sakaishun sakai

クラスに__call__メソッドを定義すると、そのクラスのインスタンスを関数のように呼び出すことができるようになります。これは「呼び出し可能オブジェクト」を作成する方法の1つ

pythonCopyclass Greeter:
    def __init__(self, greeting):
        self.greeting = greeting
    
    def __call__(self, name):
        return f"{self.greeting}, {name}!"

# インスタンスを作成
hello_greeter = Greeter("Hello")

# インスタンスを関数のように呼び出す
result = hello_greeter("Alice")
print(result)  # 出力: Hello, Alice!