您的位置:首页 > 编程语言 > Python开发

《Beginning Python From Novice to Professional》学习笔记九:More Abstraction

2009-04-20 23:10 513 查看
0.类的私有性
Python中对象的属性是可以从外部访问的,本身不直接支持私有性,对此的解释是
Isn’t it enough that each object manages its own attributes?
在Python中如果要使方法或属性从外部不可访问,则必须在名字前加上两个下划线
class Secretive: 
    def __inaccessible(self): 
        print "Bet you can't see me..." 
    def accessible(self): 
        print "The secret message is:" 
        self.__inaccessible()


方法__inaccessible则外部不可见,但实际在类的定义时,双下划线开始的方法会被自动“转换”为名字前加上单下划线再加上类名
Secretive._Secretive__inaccessible
---> <unbound method Secretive.__inaccessible>
s._Secretive__inaccessible()
---> Bet you can't see me...

1.创建类
class Person: 
    def setName(self, name): 
        self.name = name 
    def getName(self): 
        return self.name 
    def greet(self): 
        print "Hello, world! I'm %s." % self.name 

foo = Person()   #注意这里的括号 
foo.setName('hello') 
foo.greet()   #---> Hello, world! I'm hello.

习惯上第一个参数都是self,传递参数时不用写出。self是用来甄别不同的实例对象的
注意此时name属性对外是可见的。

此外实例中的函数可动态更改(注意不是类的函数)
def fun():
print "haha, You'll be terminated!"

foo.greet = fun
foo.greet() ---> haha, You'll be terminated!
以上的方法均为bound method,是与某个实例绑定的。

下面是个综合例子,结合函数一章中的几个技巧
class FoodExpert: 
    def init(self): 
        self.goodFood = [] 
    def addGoodFood(self, food): 
        self.goodFood.append(food) 
    def likes(self, x): 
        return x in self.goodFood 
    def prefers(self, x, y): 
        x_rating = self.goodFood.index(x) 
        y_rating = self.goodFood.index(y) 
        if x_rating > y_rating: 
            return y 
        else: 
            return x 
   
f = FoodExpert() 
f.init() 
map(f.addGoodFood, ['SPAM', 'Eggs', 'Bacon', 'Rat', 'Spring Surprise']) 
#---> [None, None, None, None, None]   
#返回None是因为addGoodFood

函数没有返回值
f.goodFood
---> ['SPAM', 'Eggs', 'Bacon', 'Rat', 'Spring Surprise']
menu = ['Filet Mignon', 'Pasta', 'Pizza', 'Eggs', 'Bacon', 'Tomato', 'SPAM']
rec = filter(f.likes, menu)
rec ---> ['Eggs', 'Bacon', 'SPAM']
reduce(f.prefers, rec) ---> 'SPAM'

2.类的名字空间
class MemberCounter: 
    members = 0   #相当于C++类的静态变量,可以被所有实例对象访问 
    def init(self): 
        MemberCounter.members += 1 
        self.mymember = 0 #有self空间,因此只能被创建它的实例访问 
    def add(self): 
        self.mymember += 1


m1 = MemberCounter()
m1.init()
m1.add()
m2 = MemberCounter()
m2.init()
m2.add()
MemberCounter.members ---> 2
m2.members ---> 2
m2.mymember ---> 1
但是一旦有实例对class中的变量赋值,该变量即被Rebind到该实例
m1.members = "hello"
m1.members ---> "hello"
m2.members ---> 2

3.指定SuperClassic(继承)
class Filter: 
    def init(self): 
        self.blocked = [] 
    def filter(self, sequence): 
        return [x for x in sequence if x not in self.blocked] 
   
class SPAMFilter(Filter):  #继承 
    def init(self):  #覆盖 
        self.blocked = ['SPAM']


4.判断父子关系
issubclass(SPAMFilter, Filter) ---> True
issubclass(Filter, SPAMFilter) ---> False
也可以直接得到父类
SPAMFilter.__bases__
---> (<class __main__.Filter at 0x171e40>,)
Filter.__bases__ ---> ()

5.判断是否为其实例
s = SPAMFilter()
isinstance(s, SPAMFilter) ---> True
isinstance(s, Filter) ---> True #注意这里也是True
isinstance(s, str) ---> False
也可以直接得到类信息
s.__class__ --->
<class __main__.SPAMFilter at 0x1707c0>

6.多重SuperClass(多重继承)
class Calculator: 
    def calculate(self, expression): 
        self.value = eval(expression) 
   
class Talker: 
    def talk(self): 
        print 'Hi, my value is', self.value 
   
class TalkingCalculator(Calculator, Talker): 
    pass 

#!多重继承要注意 The methods in the earlier classes override the methods in the later ones. 父类的顺序是有影响的。


7.对接口的检测
Python中不需要显式地写出接口,你可检测它
tc = TalkingCalculator()
hasattr(tc, 'talk') ---> True
hasattr(tc, 'fnord') ---> False
还可以检测是否可调用
callable(getattr(tc, 'talk', None)) ---> True
callable(getattr(tc, 'fnord', None)) ---> False
#其中getattr返回函数对象,且可以提供默认值,此处为None
#getattr的逆函数为setattr,它可以为对象增加一个属性
setattr(tc, 'name', 'Mr. Gumby')
tc.name ---> 'Mr. Gumby'
#obj.__dict__可返回obj对象的所有属性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: