面向对象

类定义形式示例如下:

class Employee:
   #定义成员变量
   empCount = 0

    #构造函数
    def __init__(self, name, salary):
       self.name = name
       self.salary = salary
       Employee.empCount += 1
    
    #定义方法
    def displayCount(self):
       print "Total Employee %d" % Employee.empCount

    #定义方法
    def displayEmployee(self):
       print "Name : ", self.name,  ", Salary: ", self.salary

基础重载方法

  1. __init__ ( self [,args...] )

    构造函数,初始化一些数据,相当于C#、Java中的 classname(args)

    简单的调用方法: obj = className(args)

  2. __del__( self )

    析构方法, 删除一个对象,相当于php的 __destruct()

    简单的调用方法 : dell obj

  3. __repr__( self )

    转化为供解释器读取的形式

    简单的调用方法 : repr(obj)

  4. __str__( self )

    用于将值转化为适于人阅读的形式,相当于Java的 toString()

    简单的调用方法 : str(obj)

  5. __cmp__ ( self, x )

    对象比较

    简单的调用方法 : cmp(obj, x)

运算符重载

除了上面的基础重载方法,还有一些方法可以重载,如运算

下例将运算符'+'重载:

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b

   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)

#结果:(7,8)
print v1 + v2

私有和公开

对于私有,Python的变量名和方法名前加两个下划线,'__attr' 和 '__method(args)'。

类内部引用私有变量和私有函数,self.__attrName 和 self.__method(args)。

类外部访问私有属性,object._className__attrName。

对于公开,Python的变量名和方法名前无双下划线。

类属性

类属性即静态属性,以Classname.attr形式引用。

类属性分为变量和方法(Python中方法也是一种属性)

  1. 变量:

    类变量即为静态变量,以Classname.attr形式引用。

    一些特殊的类属性(变量):

    • __doc__,类的文档字符串
    • __name__,类的名称
    • __base__,类的所有基类(构成的tuple)
    • __dict__,类的属性(构成的dict)
    • __module__,类所在的module
    • __class__,实例对应的类
  2. 方法:

    类方法以Classname.method()形式引用。

    @classmethod
    def cm(cls):
        print('I\'m a class method ')
    

    类方法需在方法声明上方添加@classmethod,方法至少有一个参数,参数名可随意,第一个参数代表方法所在的类。

    类方法只能访问类属性(静态属性),不能访问实例属性。

静态方法

@staticmethod
def sm():
    print('I\' a static method')

静态方法只能访问类属性(静态属性),不能访问实例属性。

实例属性

实例属性属于类的实例,引用时依赖类的实例,通过instance.arrt引用。在该类内部引用体现为self.attr,在该类外部引用体现为object.attr。

实例属性也分为变量和方法。

  1. 变量

    第一次引用实例属性(变量)时,若存在同名的类属性(变量),则实例属性(变量)的值即为类属性(变量)的值,若不存在则会抛出异常。

    第一次对实例属性(变量)赋值时,会新增或修改该属性。

  2. 方法

    类中定义的函数,第一个参数为self,指向调用该方法的实例本身。构造函数__init(self,args)__也可视为一个特殊的实例方法。

    class Person(object):
    
        def __init__(self, name):
            self.__name = name
    
        def get_name(self):
            return self.__name
    
    p1 = Person('Bob')
    print p1.get_name()  # self不需要显式传入
    

    注意上面代码中,p1.get_name() 和 p1.get_name的区别,前者是一个函数的调用,后者是一个函数。

    types.MethodType()可以动态地为实例创建方法:

    import types
    
    def fn_get_grade(self):
        if self.score >= 80:
            return 'A'
        if self.score >= 60:
            return 'B'
        return 'C'
    
    class Person(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    
    p1 = Person('Bob', 90)
    p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
    
    #输出'A'
    print p1.get_grade()
    
    

类的继承

形式:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        
class Student(Person):
    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        self.score = score

Person无父类,则定义时以Person(object)或Person()形式定义。

Student初始化时,需使用super(Student, self)获取父类,然后调用父类的构造方法(此处无self参数),否则Person将无name和gender。

isinstance(a,ClassA)方法可以判断实例a是否是ClassA类型。

Python中类可以多重继承,如Student(Person,Child)。

type(instance)

获取实例的类型

dir(instance)

获取实例的所有实例属性,list形式

getattr(instance,'attrName')

根据属性名获取实例的属性值

setattr(instance,'attrName',value)

根据属性名设置实例的属性

特殊方法

  • __str__() 将一个实例转换成一个str,用于展示给用户,那么该实例的类需要实现该方法。

  • __repr__() 将一个实例转换成一个str,用于展示给开发者,那么该实例的类需要实现该方法。

  • __cmp__() 比较方法,用于本实例与另一个相同类型的实例进行比较。 返回-1,排在前面;返回1,排在后面;返回0,两者相等。

    将学生按照分数由高到低排列,若相同,按照姓名排列。

    class Student(object):
    
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
        def __str__(self):
            return '(%s: %s)' % (self.name, self.score)
    
        __repr__ = __str__
    
        def __cmp__(self, s):
            if self.score == s.score:
                return cmp(self.name, s.name)
            return -cmp(self.score, s.score)
    
    L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)]
    print sorted(L)
    
  • __len__() 返回实例的元素的个数。

    class Fib(object):
    
    def __init__(self, num):
        a, b, L = 0, 1, []
        for n in range(num):
            L.append(a)
            a, b = b, a + b
        self.numbers = L
    
    def __str__(self):
        return str(self.numbers)
    
    __repr__ = __str__
    
    def __len__(self):
        return len(self.numbers)
    
    
    f = Fib(10)
    print f
    print len(f)
    
  • __add__() 加法

  • __sub__() 减法

  • __mul__() 乘法

  • __div__() 除法

    例如有理数的四则运算:

    def gcd(a, b):
        if b == 0:
            return a
        return gcd(b, a % b)
    
    class Rational(object):
        def __init__(self, p, q):
            self.p = p
            self.q = q
            
        def __add__(self, r):
            return Rational(self.p * r.q + self.q * r.p, self.q * r.q)
            
        def __sub__(self, r):
            return Rational(self.p * r.q - self.q * r.p, self.q * r.q)
            
        def __mul__(self, r):
            return Rational(self.p * r.p, self.q * r.q)
            
        def __div__(self, r):
            return Rational(self.p * r.q, self.q * r.p)
            
        def __str__(self):
            g = gcd(self.p, self.q)
            return '%s/%s' % (self.p / g, self.q / g)
            
        __repr__ = __str__
    
    r1 = Rational(1, 2)
    r2 = Rational(1, 4)
    print r1 + r2
    print r1 - r2
    print r1 * r2
    print r1 / r2
    

数值数据类型转换

重写__int__()和__float__()方法

class Rational(object):
    def __init__(self, p, q):
        self.p = p
        self.q = q

    def __int__(self):
        return self.p // self.q

    def __float__(self):
        return float(self.p)/self.q

print float(Rational(7, 2))
print float(Rational(1, 3))

设置属性的get和set

使用@property和@propertyname.setter来分别表示get和set操作。

@property---这是关键字,固定格式,能让方法当“属性”用。

@score.setter---前面的"score"是@property紧跟的下面定义的那个方法的名字,"setter"是关键字,这种“@+方法名字+点+setter”是个固定格式与@property搭配使用。

class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.__score = score

    @property
    def score(self):
        return self.__score

    @score.setter
    def score(self, score):
        if score < 0 or score > 100:
            raise ValueError('invalid score')
        self.__score = score

    @property
    def grade(self):
        if self.score<60:
            return 'C'
        elif self.score>80:
            return 'A'
        else:
            return 'B'

s = Student('Bob', 59)
print s.grade

s.score = 60
print s.grade

s.score = 99
print s.grade

__slots__

__slots__用于限制类能所有的属性。只对当前的类起作用,对子类不起作用。

# 限制Student只能最多拥有'name'、'gender'、'score'这三个属性,当动态再次添加额外的属性时会报错。
class Student(object):
    __slots__ = ('name', 'gender', 'score')
    def __init__(self, name, gender, score):
        self.name = name
        self.gender = gender
        self.score = score

__call__

Python中函数是对象,所有的函数都是可调用对象。类实例可变为可调用对象,需要实现__call__方法。

class Fib(object):
    
    def __call__(self,num):
        a, b, L = 0, 1, []
        for n in range(num):
            L.append(a)
            a, b = b, a + b
        return L

f = Fib()
# 输出斐波那契数列 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print f(10)
posted @ 2017-07-09 22:44  _Arvin  Views(112)  Comments(0)    收藏  举报