您的当前位置:首页正文

3、面向对象基础

来源:要发发知识网
(1)对象的声明
  • 直接给对象添加属性
class Person(object):
    pass
p1 = Person()
p1.name = 'Bart'
p2 = Person()
p2.name = 'Adam'
p3 = Person()
p3.name = 'Lisa'
  • init为每个实例都统一加上属性
  • 第一个参数必须是 self,表示对象自身
class Person(object):
    def __init__(self,name,gender,birth):
        self.name = name
        self.gender = gender
        self.birth = birth
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1')
print xiaoming.name
print xiaoming.gender
# TypeError: __init__() takes exactly 4 arguments (3 given)
# xiaohong = Person('Xiao Ming', 'Male')
  • 查看/修改实例的属性
name = getattr(xiaoming,'name')
print(name)
setattr(xiaoming,'name','jack')
print(getattr(xiaoming,'name’))
# AttributeError: 'Person' object has no attribute 'aaa'
# 获取不存在的属性报错
# getattr(xiaoming,'aaa’)
# 获取bbb属性,如果属性不存在,就返回默认值20:
print(getattr(xiaoming,'bbb',20))
  • 动态添加属性
class Person(object):
    def __init__(self, name, gender, birth, **kw):
        self.name = name
        self.gender = gender
        self.birth = birth
        for k, v in kw.iteritems():
            setattr(self, k, v)
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')
print xiaoming.name
print xiaoming.job
(2)访问权限
  • 一个属性以单下划线开头(_xxx),该属性可以被外部访问
  • 一个属性以双下划线开头(__xxx),该属性就无法被外部访问
  • 一个属性以"xxx"的形式定义,那它又可以被外部访问了,被称为特殊属性
class Person(object):
    def __init__(self, name):
        self.name = name
        self._title = 'Mr'
        self.__job = 'Student'
        self.__sex__ = "man"
p = Person('Bob')
# Bob
print p.name
# Mr
print p._title
# man
print p.__sex__
# 'Person' object has no attribute '__job'
print p.__job
(3)类属性/实例属性
  • 实例属性每个实例各自拥有,互相独立,而类属性有且只有一份
  • 类属性是直接绑定在类上的,访问类属性不需要创建实例,就可以直接访问
  • 对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性
  • 由于Python是动态语言,类属性也是可以动态添加和修改的
  • 类属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了
class Person(object):
    address = 'Earth'
    def __init__(self, name):
        self.name = name
print(Person.address)
p1 = Person('Bob')
p2 = Person('Alice')
print (p1.address) # Earth
print (p2.address) # Earth
Person.address = 'China'
print (Person.address) 
print (p1.address) # China
print (p2.address) # China
  • 类属性和实例属性名字冲突时,实例属性优先级高,它将屏蔽掉对类属性的访问。
class Person(object):
    address = 'Earth'
    def __init__(self, name):
        self.name = name
p1 = Person('Bob')
p2 = Person('Alice')
print('Person.address = ' + Person.address) # Earth
# 添加了一个实例属性address,原先的类属性address也在
p1.address = 'China'
print('Person.address = ' + Person.address)# Earth
print('p1.address = ' + p1.address) #China
print('p2.address = ' + p2.address) # Earth
# 删除p1的实例属性
del p1.address
print('p1.address = ' + p1.address) #Earth
(4)实例方法/类方法
  • 实例方法内部,可以访问所有实例属性
  • 如果外部需要访问私有属性,可以通过数据封装的形式保护内部数据一致性
class Person(object):
    def __init__(self, name):
        self.__name = name
    def getName(self):
        return self.__name
    def setName(self,name):
        self.__name = name
p1 = Person('Bob')
# __name不可以被直接访问
# print(p1.name)
print(p1.getName())
p1.setName('jack')
print(p1.getName())
  • 实例方法也可以看成类的一个属性,只不过类型是一个函数
  • 为实例添加一个属性,该属性是一个函数,并且其他实例
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)
#  A
print(p1.get_grade())
p2 = Person('Alice', 65)
# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
# 因为p2实例并没有绑定get_grade
print(p2.get_grade())
  • 直接把 lambda 函数赋值给 self.get_grade 和绑定方法有所不同,函数调用不需要传入 self
class Person(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
        self.get_grade = lambda: 'A'  #lambdar匿名函数
p1 = Person('Bob', 90)
# <function Person.__init__.<locals>.<lambda> at 0x10caf61e0>
print(p1.get_grade) 
# A
print(p1.get_grade())
  • 类方法
  • 通过标记一个 @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()) # 0
p1 = Person('Bob')
print(Person.how_many()) # 1
p1 = Person('Jack')
print(Person.how_many()) # 2
print(p1.how_many()) # 2