美文网首页
python面向对象之基本篇

python面向对象之基本篇

作者: 为瞬间停留 | 来源:发表于2018-04-17 20:44 被阅读11次

    在学习python面向对象的时候,确保自己对python基础已经有所掌握,包括python安装使用,python基本数据类型,python逻辑结构,python函数的使用等。

    1.第一个例子,创建类

    import sys
    class Person(object):
        pass
    
    if __name__ == '__main__':
        xiaoming = Person()
        xiaohong = Person()
    
        print xiaoming
        print xiaohong
        print xiaoming == xiaohong
    

    上面的例子创建了一个Person类,实例化了两个对象,并打印它们的先关信息。

    2.创建实例属性

    class Person(object):
        pass
    
    p1 = Person()
    p1.name = 'Bart'
    
    p2 = Person()
    p2.name = 'Adam'
    
    p3 = Person()
    p3.name = 'Lisa'
    
    L1 = [p1, p2, p3]
    
    #排序,sort()方法会改变list,可以使用key指定排序参数
    #lambda A:B   A为参数,B为返回,使用中x表示的是list中的元素
    L2 = sorted(L1,key=lambda x:x.name)
    
    print L2[0].name
    print L2[1].name
    print L2[2].name
    

    实例化了三个对象,并创建了name属性,并进行了排序的操作。

    3.python中初始化实例属性

    class Person(object):
        def __init__(self,name,sex,birth,**kwargs):
            self.name = name
            self.sex = sex
            self.birth = birth
            for k,v in kwargs.items():
                setattr(self,k,v)
    #可变参数**kwargs当成字典来处理,*args直接for i in args
    xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')
    
    print xiaoming.name
    print xiaoming.job
    

    初始化示例的属性,必须定义构造函数init函数,它的第一个参数必须是self表示本对象,使用的时候,直接使用类名类似函数的调用,可以传入不定数量的参数。

    4.python中访问限制

    class Person(object):
        def __init__(self, name, score):
            self.name = name
            self.__score = score
    
    p = Person('Bob', 59)
    
    print p.name
    print p.__score
    有错误,__score成员不能被外部访问。
    

    以__开头命令的属性,是不能被外部访问的,可以在类里面访问,如果你想访问,可以试图在类里面定义一个函数返回此属性值,外部通过这个函数进行访问

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

    #因为类属性是直接绑定在类上的,所以,访问类属性不需要创建实例,就可以直接访问
    #对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性
    class Person(object):
        count = 0
        def __init__(self,name):
            self.name = name
            Person.count = Person.count + 1
    
    p1 = Person('Bob')
    print p1.count
    
    p2 = Person('Alice')
    print p2.count
    
    p3 = Person('Tim')
    print p3.count
    

    6.类属性和实例属性名字冲突

    # 我们发现,在设置了 p1.address = 'China' 后,p1访问 address 确实变成了 'China',
    # 但是,Person.address和p2.address仍然是'Earch',怎么回事?
    # 原因是 p1.address = 'China'并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address ,
    # 对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:
    # 访问 p1.address 时,优先查找实例属性,返回'China'。
    # 访问 p2.address 时,p2没有实例属性address,但是有类属性address,因此返回'Earth'。
    # 可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问
    class Person(object):
        address = 'Earth'
        def __init__(self, name):
            self.name = name
    
    p1 = Person('Bob')
    p2 = Person('Alice')
    
    print 'Person.address = ' + Person.address
    
    p1.address = 'China'
    print 'p1.address = ' + p1.address
    
    print 'Person.address = ' + Person.address
    print 'p2.address = ' + p2.address
    

    类属性也可以定义成外部不能直接访问的。

    #__count的值会随着对象的创建递增,只是外部访问不到
    class Person(object):
        __count = 0
        def __init__(self, name):
            Person.__count = Person.__count + 1
            self.name = name
            print Person.__count
    
    p1 = Person('Bob')
    p2 = Person('Alice')
    
    #print Person.__count
    

    7.python中定义实例方法
    一个实例的私有属性就是以__开头的属性,无法被外部访问,那这些属性定义有什么用?

    虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。

    实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:

    class Person(object):
    
        def __init__(self, name, score):
            self.__name = name
            self.__score = score
    
        def get_grade(self):
            if self.__score >= 80:
                return 'A'
            if self.__score >= 60:
                return 'B'
            return 'C'
    
    p1 = Person('Bob', 90)
    p2 = Person('Alice', 65)
    p3 = Person('Tim', 48)
    
    print p1.get_grade()
    print p2.get_grade()
    print p3.get_grade()
    

    8.python中方法也是属性
    我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象,因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法.给一个实例动态添加方法并不常见,直接在class中定义要更直观.

    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()
    p2 = Person('Alice', 65)
    
    #print p2.get_grade()
    #ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
    #因为p2实例并没有绑定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。
    9.python中定义类方法
    和属性类似,方法也分实例方法和类方法。
    在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。
    要在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
    
    print Person.how_many()
    p1 = Person('Bob')
    print Person.how_many()
    

    通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
    因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

    #没有问题,通过方法获取私有类属性值
    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()
    

    相关文章

      网友评论

          本文标题:python面向对象之基本篇

          本文链接:https://www.haomeiwen.com/subject/iixohftx.html