Python学習(五)

7794 ワード

クラスとオブジェクト
#     ,           ,           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を使う
  • は、1つのクラスの動的なバインディング属性と方法
      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'
    
  • slaots定義の属性は現在のクラスのインスタンスにのみ作用し、継承されたサブクラスには役に立たない。
    @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