美文网首页
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