面向对象编程(一)

# setattr 动态添加或者修改属性
attr_dict = {'iq': '150', 'eq': '150', 'color': 'yellow'}
t = (1,2,3)
t = 1,2
print(attr_dict.items())
# for循环遍历字典
for key,value in attr_dict.items():
    # key是属性名 value是属性值
    # setattr,可以将一个字符串的属性名 添加到对象的属性中
    # p1.key = value 这种方式无法添加 相当于写了 p1.'iq' = '150'
    setattr(p1, key, value)

 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例self,并且,调用 时,不用传递该参数。除此之外,类的方法和普通函数,没有区别。类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:


访问限制

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。但是如果外部代码要获取name和score怎么办?可以给Student类增加get_nameget_score这样的方法:

class Student(object):
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score
 def set_score(self, score):
        self.__score = score
错误写法
>>> bart = Student('Bart Simpson', 59)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # 设置__name变量!
>>> bart.__name
'New Name'
>>> bart.get_name() # get_name()内部返回self.__name
'Bart Simpson'
表面上看,外部代码“成功”地设置了 __name变量,但实际上这个 __name变量和class内部的 __name变量 不是一个变量!内部的 __name变量已经被Python解释器自动改成了 _Student__name,而外部代码给 bart新增了一个 __name变量

动态语言的继承

静态语言 vs 动态语言

对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。

对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了:

class Timer(object):
    def run(self):
        print('Start...')

这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()方法,返回其内容。但是,许多对象,只要有read()方法,都被视为“file-like object“。许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,完全可以传入任何实现了read()方法的对象。

类中方法

类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法

>>> class MyDog(object):
...     def __len__(self):
...         return 100
...
>>> dog = MyDog()
>>> len(dog)
100
配合 getattr()setattr()以及 hasattr(),我们可以直接操作一个对象的状态:

>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19
>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81

类属性和实例属性

关于Python类属性与实例属性的讨论

2
3
4
5
6
7
8
9
10
11
12
13
14
15
class AAA ( ) :   
     aaa = 10   
 
# 情形1  
obj1 = AAA ( )   
obj2 = AAA ( )   
print obj1 . aaa , obj2 . aaa , AAA . aaa   
 
# 情形2  
obj1 . aaa += 2   
print obj1 . aaa , obj2 . aaa , AAA . aaa   
 
# 情形3  
AAA . aaa += 3   
print obj1 . aaa , obj2 . aaa , AAA . aaa   

情形1的结果是:10 10 10
情形2的结果是:12 10 10
情形3的结果是:12 13 13
1. Python中属性的获取是按照从下到上的顺序来查找属性;
2. Python中的类和实例是两个完全独立的对象;
3. Python中的属性设置是针对对象本身进行的

class Student(object):
    count = 0
    def __init__(self, name):
        Student.count=Student.count+1
        self.name = name
//类中属性赋值也需加类名

# setattr 动态添加或者修改属性
attr_dict = {'iq': '150', 'eq': '150', 'color': 'yellow'}
t = (1,2,3)
t = 1,2
print(attr_dict.items())
# for循环遍历字典
for key,value in attr_dict.items():
    # key是属性名 value是属性值
    # setattr,可以将一个字符串的属性名 添加到对象的属性中
    # p1.key = value 这种方式无法添加 相当于写了 p1.'iq' = '150'
    setattr(p1, key, value)
delatter动态删除属性同理

类方法和实例方法

pass

class Student(object):
    pass

s = Student()
s.name = 'Michael' # 动态给实例绑定一个属性
print(s.name)

def set_age(self, age): # 定义一个函数作为实例方法
    self.age = age


from types import MethodType
s.set_age=MethodType(set_age,s)# 给实例绑定一个方法

s.set_age(25)
print(s.age)

s1=Student()
Student.set_age=set_age         # 给类绑定一个方法
s2=Student()
s2.set_age(11)
s1.set_age(11)
print(s2.age,s1.age)   #给class绑定方法后,所有实例均可调用:



为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age'
>>> s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

使用 __slots__要注意, __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值