zoukankan      html  css  js  c++  java
  • Python面向对象--高级(一)

    ## 属性的类型
      - 属性可分为类属性和实例属性

      - 实例属性可以通过在类中使用self定义,或者直接在类外部使用实例变量定义

     1 class Person(object):
     2     def __init__(self, name, age):
     3         self.name = name
     4         self.age = age
     5 
     6 
     7 per1 = Person("Stanley", 22)
     8 print(per1.name)        # 输出:Stanley
     9 per1.weight = "50kg"    
    10 print(per1.weight)      # 输出:50kg

      - 类属性则直接在类中定义
        - 类属性通过类名访问,也可以通过实例访问

     1 class Person(object):
     2     class_name = "Person"
     3 
     4     def __init__(self, name, age):
     5         self.name = name
     6         self.age = age
     7 
     8 
     9 per1 = Person("Stanley", 22)
    10 print(per1.class_name)      # 输出:Person
    11 
    12 print(Person.class_name)    # 输出:Person

      - 注意:
        - 如果实例属性和类属性使用了相同的名字,则实例化后实例属性将覆盖类属性,实例将无法在访问该同名类属性,而通过类名访问类属性将不受影响

     1 class Person(object):
     2     name = "Person"
     3 
     4     def __init__(self, name, age):
     5         self.name = name
     6         self.age = age
     7 
     8 
     9 print(Person.name)      # 输出:Person
    10 
    11 per1 = Person("Stanley", 22)
    12 print(per1.name)        # 输出:Stanley
    13 print(Person.name)      # 输出:Person

    ## 方法的类型
      - 在一个类中可以存在三种类型的方法
      - 在类的定义中,以self(即实例本身)作为第一个参数的方法为实例方法

     1 class Person(object):
     2 
     3     def __init__(self, name, age):
     4         self.name = name
     5         self.age = age
     6 
     7     # 这是一个实例方法,self为实例本身,作为第一个参数传入,通过实例调用
     8     def eat(self):
     9         print("I'm %s, I want to eat!" % self.name)
    10 
    11 
    12 per1 = Person("Stanley", 22)
    13 per1.eat()      # 输出:I'm Stanley, I want to eat!

      - 在类的内部定义,用修饰符@classmethod指定的方法是类方法
      - 类方法会作用于整个类,该方法对类做出的改变会影响该类的所有实例
      - 与实例方法类似,类方法的第一个参数是类本身,通常写作cls

    class Person(object):
        count = 0
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
            Person.count += 1   # 每实例化一个对象,count加1
    
        # 这是一个实例方法,self作为第一个参数传入,通过实例调用
        def eat(self):
            print("I'm %s, I want to eat!" % self.name)
    
        @classmethod        # 使用@classmethod修饰
        def kids(cls):      # 第一个参数为类本身,这是一个类方法
            print("class %s has %d instance(es)." % (cls.__name__, Person.count))
    
    
    per1 = Person("Stanley", 22)
    per2 = Person("Bob", 18)
    per3 = Person("Lily", 17)
    Person.kids()       # 输出:class Person has 3 instance(es).

      - 第三种方法类型称为静态方法
      - 静态方法使用@staticmethod修饰,它不需要self参数或者cls参数
      - 静态方法的存在不会影响类也不会影响类的实例,仅仅是为了代码的逻辑性
      - 静态方法可以通过类名或者实例调用

     1 class Person(object):
     2     def __init__(self, name, age):
     3         self.name = name
     4         self.age = age
     5 
     6     @staticmethod
     7     def say_hi():
     8         print("I'm a static method. I say Hi.")
     9 
    10 
    11 per1 = Person("Stanley", 22)
    12 per1.say_hi()       # 输出:I'm a static method. I say Hi.
    13 Person.say_hi()     # 输出:I'm a static method. I say Hi.

    ## 使用property对attribute进行访问和设置
      - 对于一些语言比如Java来说,对于私有属性的访问需要使用setter和getter方法
      - Python不需要,因为Python所有属性都是公开的,但是也可以编写setter和getter限制对属性的访问

     1 class Person(object):
     2     def __init__(self, name, age):
     3         self.__name = name  # 私有属性
     4         self.age = age
     5 
     6     def set_name(self, name):
     7         self.__name = name
     8 
     9     def get_name(self):
    10         return self.__name
    11 
    12 
    13 per1 = Person("Stanley", 22)
    14 print(per1.get_name())      # 输出:Stanley
    15 per1.set_name("Lily")       # 修改属性值
    16 print(per1.get_name())      # 输出:Lily
    17 print(per1.__name)          # 无法直接访问私有属性,AttributeError: 'Person' object has no attribute '__name'

      - 以上写法达到了限制访问的目的

      - 但更Pythonic的写法是使用property()

     1 class Person(object):
     2     def __init__(self, name, age):
     3         self.__name = name
     4         self.age = age
     5 
     6     def set_name(self, name):
     7         self.__name = name
     8 
     9     def get_name(self):
    10         return self.__name
    11 
    12     # 使用property函数将getter和setter定义为了name属性
    13     name = property(get_name, set_name)
    14 
    15 
    16 per1 = Person("Stanley", 22)
    17 print(per1.name)        # 访问属性时自动调用getter方法,输出:Stanley
    18 per1.name = "Lily"      # 设置属性时自动调用setter方法
    19 print(per1.name)        # 输出:Lily
    20 print(per1.get_name())  # 也可以显式的调用getter或者setter方法

      - 还有一种方法进行访问限制,那么就是使用修饰符,并定义两个同名方法

     1 class Person(object):
     2     def __init__(self, name, age):
     3         self.__name = name
     4         self.age = age
     5 
     6     @property       # @property 用于指示getter方法
     7     def name(self): # 两个同名函数
     8         return self.__name
     9 
    10     @name.setter    # @name.setter 用于指示setter方法
    11     def name(self, name):   # 两个同名函数
    12         if isinstance(name, str):
    13             self.__name = name
    14         else:
    15             raise TypeError("Name must be string!")
    16 
    17 
    18 per1 = Person("Stanley", 22)
    19 print(per1.name)    # 输出:Stanley
    20 per1.name = "Lily"
    21 print(per1.name)    # 输出:Lily

      - 使用了@property修饰的方法就变成了属性

     1 import datetime
     2 
     3 
     4 class Person(object):
     5     def __init__(self, name, age):
     6         self.__name = name
     7         self.age = age
     8 
     9     @property
    10     def birth_year(self):
    11         return datetime.datetime.now().year - self.age
    12 
    13 
    14 per1 = Person("Stanley", 22)
    15 print(per1.birth_year)      # 输出:1996
    16 per1.birth_year = 2000      # 没有指定setter属性(@birth_year.setter),所以无法从外部对它的值进行设置,这使得这个birth_year这个属性成为只读属性

    本文参考:

      [美]Bill Lubanovic 《Python语言及其应用》

  • 相关阅读:
    jqgard改变单元格后重新定值(事件和弹窗)
    js多个input框赋相同值
    查看PHP已安装拓展的指令
    PHP重新安装zlib拓展,处理PHP Startup: Invalid library (maybe not a PHP library) 'zlib.so' in Unknown
    php拓展安装报错:PHP Startup: Invalid library (maybe not a PHP library) 'zlib.so' in Unknown
    Composer提示:Installation Failed, Reverting ./Composer.Json To Its Original Content.错误的解决办法
    SQL Server序列号的获取
    一步步开发Windows服务(Windows Service)[转]
    HTML+CSS+JS实现的贪吃球小游戏【转】
    自制一个滚动条
  • 原文地址:https://www.cnblogs.com/hycstar/p/9251976.html
Copyright © 2011-2022 走看看