Python学習(五)
7794 ワード
クラスとオブジェクト
slaotsを使うは、1つのクラスの動的なバインディング属性と方法 を与える。限定例の属性 slaots定義の属性は現在のクラスのインスタンスにのみ作用し、継承されたサブクラスには役に立たない。
@propertyを使う
属性の変更と取得は、インスタンスオブジェクトから直接属性を取得して修正することができますが、この属性がprvateであれば変更できません。そして、クラス外で提供されるsetやget方法で属性や修正を取得することもできますが、これはちょっとややこしいです。パラメータをチェックしたり、属性のような簡単な方法でクラスにアクセスできる変数がありますか?前に習った装飾器が関数に動的に機能を付けられます。Pythonに内蔵されている@property装飾器は一つの方法を属性に変えて呼び出すのを担当しています。
一つのクラスは他のクラスを引き継ぐことができますが、これまでは単独で継承されていましたので、追加の機能を「混入」する必要があります。Pythonでは、このデザインをMixInと呼びます。
クラスのカスタマイズ
Enumは一つのグループの関連定数を一つのクラスに定義してもいいし、クラスは変わらないし、メンバーも直接比較できます。
# , , object
class Student(object):
#
age = 18
# Java ,
def __init__(self, name, score, sex):
#
self.name = name
self.score = score
# "__" private ,
self.__sex = sex
"""
, : self, ;
self
"""
def print_info(self):
print("%s,%d,%s" % (self.name, self.score, self.__sex))
"""
set、get ,
"""
def set_sex(self, sex):
self.__sex = sex
def get_sex(self):
return self.__sex
# ,
s = Student("Blain", 90, "male")
s.print_info() # Blain,90,male
s.score = 95
s.print_info() # Blain,95,male
s.set_sex("female")
print(s.get_sex()) # female
#
print(hasattr(s, "name")) # True
#
print(hasattr(s, "grade")) # False
#
setattr(s, "grade", 9)
print(hasattr(s, "grade")) # True
#
# print(getattr(s, "address"))
#
print(getattr(s, "address", " ")) #
#
fn = getattr(s, "print_info")
print(fn) # >
fn() # Blain,95,female
# , ,
print(Student.age) # 18
print(s.age) # 18
オブジェクト指向プログラミングslaotsを使う
from types import MethodType
class People(object):
pass
p1 = People()
p2 = People()
# p1 name
p1.name = "Blain"
#
def set_age(self, age):
self.age = age
# p1
p1.set_age = MethodType(set_age, p1)
print(p1.name) # Blain
p1.set_age(18)
print(p1.age) # 18
# ,
# p2.set_age(19) # AttributeError: 'People' object has no attribute 'set_age'
# , class :
def set_score(self, score):
self.score = score
People.set_score = set_score
p1.set_score(80)
print(p1.score) # 80
p2.set_score(90)
print(p2.score) # 90
class People2(object):
# tuple
__slots__ = ("name", "age")
p3 = People2()
p3.name = "Tom"
p3.age = 16
# p3.score = 99 # AttributeError: 'People2' object has no attribute 'score'
@propertyを使う
属性の変更と取得は、インスタンスオブジェクトから直接属性を取得して修正することができますが、この属性がprvateであれば変更できません。そして、クラス外で提供されるsetやget方法で属性や修正を取得することもできますが、これはちょっとややこしいです。パラメータをチェックしたり、属性のような簡単な方法でクラスにアクセスできる変数がありますか?前に習った装飾器が関数に動的に機能を付けられます。Pythonに内蔵されている@property装飾器は一つの方法を属性に変えて呼び出すのを担当しています。
class Student(object):
@property
def score(self):
return self.__score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError("score must be integer")
if value < 0 or value > 100:
raise ValueError("score must be between 0 ~ 100")
self.__score = value
s = Student()
s.score = 30 # s.set_score(60)
print(s.score) # 30 s.get_score()
s.score = 1000
print(s.score) # ValueError: score must be between 0 ~ 100
多重継承一つのクラスは他のクラスを引き継ぐことができますが、これまでは単独で継承されていましたので、追加の機能を「混入」する必要があります。Pythonでは、このデザインをMixInと呼びます。
class Animal(object):
pass
class Mamal(Animal):
pass
class Bird(Animal):
pass
class RunnableMixIn(object):
def run(self):
print(" ")
class FlyableMixIn(object):
def fly(self):
print(" ")
class Dog(Mamal, RunnableMixIn):
pass
# , ,
class Parrot(Bird, FlyableMixIn):
pass
ただし、Javaでは、一つのクラスは単一継承しかできないので、MixInというデザインはJavaには適用されません。クラスのカスタマイズ
class Student(object):
def __init__(self, name):
self.name = name
self.a, self.b = 0, 1 # a,b
# , java toString ,
def __str__(self):
return "Student object (name: %s)" % self.name
# , , ; __str__
__repr__ = __str__
# for ... in , __iter__
def __iter__(self):
return self # ,
# for __next__ , StopIteration
def __next__(self):
self.a, self.b = self.b, self.a + self.b #
if self.a > 20:
raise StopIteration
return self.a
# Student list
def __getitem__(self, item):
a, b = 1, 1
if isinstance(item, int): # item
for x in range(item):
a, b = b, a + b
return a
if isinstance(item, slice): # item
start = item.start
stop = item.stop
if start is None:
start = 0
l = []
for x in range(stop):
if x >= start:
l.append(a)
a, b = b, a + b
return l
# ,Python
# , 。
def __getattr__(self, attr):
if attr == "sex":
return "Male"
raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
# , , ,
# , , ? callable
def __call__(self):
print("My name is %s" % self.name)
# print(Student("Blain")) # Student object (name: Blain)
# for n in Student("Blain"):
# print(n) # 1,1,2,3,5,8,13
s = Student("Blain")
# print(s[0]) # 1
# print(s[1]) # 1
# print(s[2]) # 2
# print(s[3]) # 3
# print(s[4]) # 5
# print(s[:5]) # [1,1,2,3,5]
# print(s.age) # AttributeError: 'Student' object has no attribute 'age'
print(callable(s)) # True
print(callable("test")) # False
列挙クラスを使うEnumは一つのグループの関連定数を一つのクラスに定義してもいいし、クラスは変わらないし、メンバーも直接比較できます。
from enum import Enum, unique
Month = Enum("Month", ("Jan", "Feb", "Mar", "Apr", "May", "June", "July"))
#
print(Month.Jan) # Month.Jan
#
for name, member in Month.__members__.items():
# value int , 1
print(name, "=>", member, ",", member.value)
# Jan => Month.Jan , 1
# Feb => Month.Feb , 2
# Mar => Month.Mar , 3
# Apr => Month.Apr , 4
# May => Month.May , 5
# June => Month.June , 6
# July => Month.July , 7
#
@unique # @unique
class Weekday(Enum):
Sun = 0 # Sun Value 0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
d1 = Weekday.Mon
print(d1) # Weekday.Mon
print(Weekday.Mon) # Weekday.Mon
print(Weekday["Mon"]) # Weekday.Mon
print(Weekday(1)) # Weekday.Mon
print(Weekday.Mon.value) # 1
print(d1 == Weekday(1)) # True
print(d1 == Weekday.Mon) # True