python——面向对象编程

 

面向对象的基本思想:

     1.  用于定义抽象的类型, 实例根据类的定义被创建

 

python之定义类并创建实例

   

在Python中,类通过 class 关键字定义。以 Person 为例,定义一个Person类如下:

class Person(object):
    pass

按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的

 class Person():
  pass
 

python中创建实例属性

如何让每个实例拥有各自不同的属性?由于Python是动态语言,对每一个实例,都可以直接给他们的属性赋值,

例如,给xiaoming这个实例加上name、genderbirth属性:

 

 

 
xiaoming = Person()
xiaoming.name = 'Xiao Ming'
xiaoming.gender = 'Male'
xiaoming.birth = '1990-1-1'

xiaohong加上的属性不一定要和xiaoming相同:

xiaohong = Person()
xiaohong.name = 'Xiao Hong'
xiaohong.school = 'No. 1 High School'
xiaohong.grade = 2



class Person(object):
    pass
p1 = Person()
p1.name = 'Bart'
p2 = Person()
p2.name = 'Adam'
p3 = Person()
p3.name = 'Lisa'
L1 = [p1, p2, p3]
L2 = sorted(L1, lambda p1,p2:cmp(p1.name, p2.name))
print L2[0].name
print L2[1].name
print L2[2].name

python中初始化实例属性

我们可以自由地给一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥有相同名字的属性。例如,Person类应该在创建的时候就拥有 name、gender 和 birth 属性,怎么办?

在定义 Person 类时,可以为Person类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:

class Person(object):
    def __init__(self, name, gender, birth):
        self.name = name
        self.gender = gender
        self.birth = birth

__init__() 方法的第一个参数必须是 self(也可以用别的名字,但建议使用习惯用法),后续参数则可以自由指定,和定义函数没有任何区别。

 

 

 

class Person(object):
    def __init__(self,name,gender,birth,*args,**kw):
        self.name=name
        self.gender=gender
        self.birth=birth
        for i in args:
            print i
        for k,v in kw.items():
            setattr(self,k,v)
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', '33',job='Student')
print xiaoming.name
print xiaoming.job
 

Python参数组合

参数定义的顺序必须是:①必选参数、②默认参数、③可选参数、④命名关键字参数、⑤关键字参数

 
 #参数定义的顺序必须是:必选参数、默认参数、可选参数、命名关键字参数、关键字参数
6 def f2(a,b,c=0,*,d,**kw):
7     print('a=','b=',b,'c=','d=',d,'kw=',kw)
 

python中访问限制

Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无法被外部访问

 

 

但是,如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。

以单下划线开头的属性"_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问

 

 class Person(object):
    def __init__(self,name):
        self.name=name
        self._title='Mr'
        self.__job = 'Student'
p=Person('Bob')
print (p.name)
print (p._title)
print (p.job)

 

 

Bob
Mr
Traceback (most recent call last):
  File "D:\test2.py", line 396, in <module>
    print (p.job)
AttributeError: 'Person' object has no attribute 'job

 

python中创建类属性

类是模板,而实例则是根据类创建的对象。

绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

 

 

 

 class Person(object):
    address = 'Earth'
    def __init__(self,name):
        self.name=name
p=Person('test')
print (p.name)
print (p.address)  所有实例都可以访问到它所属的类的属性:
print (p.name)

 

>>Earth
>>test

 

由于Python是动态语言,类属性也是可以动态修改的:

Person.address = 'China'
print p1.address
# => 'China'
print p2.address
# => 'China'

因为类属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了。

类属性也是可以动态添加:

Person.age=25
print (p.age)

>>25

 

 

请给 Person 类添加一个类属性 count,每创建一个实例,count 属性就加 1,这样就可以统计出一共创建了多少个 Person 的实例:

 

class Person(object):
    count=0
    def __init__(self,name):
        self.name=name
        Person.count=Person.count+1
p1 = Person('Bob')
print Person.count
p2 = Person('Alice')
print Person.count
p3 = Person('Tim')
print Person.count

 

python中类属性和实例属性名字冲突怎么办

 

当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

 

 
class Person(object):
    __count = 0
    def __init__(self, name):
        self.name=name
        Person.__count=Person.__count+1
        print Person.__count  :可以访问
p1 = Person('Bob')
p2 = Person('Alice')
#print Person.__count  : 外部无法访问
 
私有属性无法从外部访问,但是,从类的内部是可以访问的
 

python中定义实例方法

 

 

 
class Person(object):

    def __init__(self, name):
        self.__name = name

    def get_name(self):
        return self.__name

如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。
 

python中方法也是属性

我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象

方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 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)
print p1.get_grade()
# => A
p2 = Person('Alice', 65)
print p2.get_grade()
# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'




由于属性可以是普通的值对象,如 str,int 等,也可以是方法,还可以是函数,大家看看下面代码的运行结果,
请想一想 p1.get_grade 为什么是函数而不是方法:


class Person(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
        self.get_grade = lambda: 'A'
p1 = Person('Bob', 90)
print p1.get_grade
print p1.get_grade()
 
直接把 lambda 函数赋值给 self.get_grade 和绑定方法有所不同,函数调用不需要传入 self,但是方法调用需要传入 self
 

python中定义类方法

 

和属性类似,方法也分实例方法和类方法。

 

通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count

 

要在class中定义类方法,需要这么写:

class Person(object):
    count = 0
    @classmethod
    def how_many(cls):
        return cls.count
    def __init__(self, name):
        self.name = name
        Person.count = Person.count + 1


class Person(object):
    __count = 0
    @classmethod
    def how_many(cls):
       
        return cls.__count
    def __init__(self,name):
        self.name = name
        Person.__count=Person.__count+1
print Person.how_many()
p1 = Person('Bob')
print Person.how_many()  通过类方法获取类的私有变量。
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
posted on 2020-05-22 08:51  肉松蛋卷  阅读(176)  评论(0)    收藏  举报