快乐学习
前程无忧、中华英才非你莫属!

Day7-人生苦短我学python

Python:面向对象的编程语言,多态,封装,继承三个主要特性

多态:来自希腊语,意味着有多种形式。

- >>> from random import choice
- >>> x = choice(['Hello,World!',[1,2,'e','e',4]])
- >>> x.count('e')
- 1

任何不知道对象到底是什么类型,但又要对对象做的什么的时候,就要用到多态

- >>> 1+2

- 3

- >>> 'hot'+'dog'

- 'hotdog'

#和下面的形式是一样的

- >>> def add(x,y): return x+y
- ...
- >>> add(1,2)
- 3

- >>> add('hot','dog')
- 'hotdog'

#如果要打印信息的长度,只需要对象具有长度即可.

- >>> def print_message(x):
- ...     print 'The length of',repr(x),'is',len(x)
- ...

用到的repr()就是多态特性的代表之一:可以对任何东西使用.

- >>> print_message('Fnord')
- The length of 'Fnord' is 5

- >>> print_message([1,2,3,4])
- The length of [1, 2, 3, 4] is 4

事实上,唯一能毁掉多态的就是函数显示的检查类型,比如:type,isinstance,issubclass,如果可能的话,尽量避免这些毁掉多态函数的方式。真正重要的是如何让对象按照我们的方式工作。

 

封装:是对全局作用域中其他区域隐藏多余信息的原则。

多态:使用对象,而不用知道其内部细节

两者概念类似,但是封装不等同于多态

多态可以让用户对于不知道是什么类的对象进行方法调用,而封装是可以不用关心对象是如何创建而直接使用。

 

继承:是一种“懒惰”的行为,程序员不想把代码写几次。

类:一种对象. 鸟类(supperclass)-->百灵鸟(subclass)

Note: python的类名,不用复数,首字母大写,如果多个单词,首字母同样大写Bird

创建自定义类:

 

 

class Person:
     def setName(self, name):
          self.name = name

     def getName(self, name):
          return self.name

     def greet(self):
          print "Hello,World! I am %s" % self.name

foo = Person()
bar = Person()
foo.setName('Luke Skywalker')
bar.setName('Anakin Skywalker')
foo.greet()
bar.greet()

 

self: 对象自身

 

特性,函数和方法

self事实上正是方法与函数的区别,方法将它们的第一个参数绑定到实例上,实在理解不了就想想JAVA中的This!

- >>> class Class:
-         def method(self):
-             print 'I have a self!'

- >>> def function():
-         print "I don't..."

- >>> instance = Class()
- >>> instance.method()
- I have a self!
- >>> instance.method = function
- >>> instance.method()
- I don't...
- >>> class Bird:
-         song = 'Squaawk!'

-         def sing(self):
-              print self.song
-

- >>> bird = Bird()
- >>> bird.sing()
- Squaawk!
- >>> birdsong = bird.sing
- >>> birdsong()
- Squaawk!

 

私有化:

在方法前面加__,表示私有方法,不可直接访问:(java中需要用修饰符来控制,private)

- >>> class Secretive:
-         def __inaccessible(self):
-              print "Bet you can't see me..."

-         def accessible(self):
-              print "The scret message is:"

-              self.__inaccessible()
- >>> s = Secretive()
- >>> s.__inaccessible()  #不能直接访问

- Traceback (most recent call last):
-   File "<pyshell#29>", line 1, in <module>
-     s.__inaccessible()
- AttributeError: Secretive instance has no attribute '__inaccessible'

- >>> s.accessible()      #但能通过其他方法来访问

- The scret message is:
- Bet you can't see me...

#不能被外界直接使用,但可以再类内部使用,从而达到间接调用该方法.

#还有一种访问方法,要体会如何使用,主要是用于测试,看下面

- >>> Secretive._Secretive__inaccessible
- <unbound method Secretive.__inaccessible>

#提示未绑定的方法,只要在前面用instance来绑定就可以了。

- >>> dir(Secretive)
- ['_Secretive__inaccessible', '__doc__', '__module__', 'accessible']
- #dir()函数也可以看到

- instance._ClassName__PrivateMethod()
- >>> s._Secretive__inaccessible()
- Bet you can't see me...

Note: 如果不需要使用这种方法,但是又想让其他对象不要访问内部数据,那么可以使用单下划线。

前面有单下划线的不会被from module import * 语句导入

 

类的命名空间:

#下面两个函数应该是一样的

- >>> def foo(x): return x*x
- ...
- >>> foo = lambda x:x*x

#定义类时也一样,所有class语句中的代码都在类命令空间中执行,由类内所有成员访问.类的定义其实就是执行class语句中的代码块.这点非常有用,比如说类的语句并不仅限于def,比如下面的也是一样:

- >>> class C:
- ...     print "class C is being defined..."

- ...
- class C is being defined...

再比如像下面的:

- >>> class MemberCounter:
- ...     members = 0

- ...     def init(self):
- ...         MemberCounter.members +=1

- ...
- >>> m1 = MemberCounter()
- >>> m1.init()
- >>> m1.members
- 1

- >>> m2 = MemberCounter()
- >>> m2.init()
- >>> MemberCounter.members
- 2

也可以像下面这样让其自动初始化

- >>> class MC:
- ...     m = 0

- ...     def __init__(self):
- ...         self.m +=1

- ...
- >>> m1 = MC()
- >>> m1.m
- 1

 

Note: Java 支持4中级别,尽管Python给出了单双下划线,但Python并没有真正的私有化支持

如果在实例中重新绑定members呢? 

- >>> m1.members = 'Two'

- >>> m1.members
- 'Two'

- >>> m2.members
- 2

#这跟函数的局部,全局变量非常类似

 

指定超类:

- class Filter:
-     def __init__(self):
-         self.blocked = []      #self.不能少

-     def filter(self,sequence): #注意这种写法,非常有用

-         return [x for x in sequence if x not in self.blocked]
-

- class SPAMFilter(Filter):      #继承自父类或超类:Filter

-     def __init__(self):        #重写超类中的__init__方法

-         self.blocked = ['SPAM']
-

- f1 = Filter()                  #实际上这个什么也没有过滤,[]

- print f1.filter([1,2,3])
-

- s = SPAMFilter()               #过滤掉了列表中所有含'SPAM'的元素

- print s.filter(['SPAM','eggs','SPAM','bacon','SPAM'])

输出结果:

- >>>
- [1, 2, 3]
- ['eggs', 'bacon']

NOTE: 注意子类SPAMFilter要点:

1. 重写Filter的init初始化方法

2. filter的方法继承自父类(Filter),不用重写.

第二点解示了继承的好处,我们可以写一大堆过滤的类,全部继承自Filter.

每个类都可以使用超类中,已经实现的方法:filter()

 

调查继承:

  • 如何判断某类是否是另外一个类的子类呢,用Python自置的类issubclass(子类,父类)
- >>> issubclass(SPAMFilter,Filter)
- True
  • 如果想要知道已经类的基类,可以用它的特殊属性__bases__
- >>> Filter.__bases__
- ()
- >>> SPAMFilter.__bases__
- (<class __main__.Filter at 0x00000000029E2DC8>,)
  • 如果想判断一个对象是否是一个类的实例,可以用isinstance
- >>> s = SPAMFilter()
- >>> isinstance(s,SPAMFilter)
- True

- >>> isinstance(s,Filter) #同样是超类的一个对象

- True

- >>> isinstance(s,str)
- False

Note: 使用isinstance并不是个好习惯,使用多态好些.

  • 如果想知道一个对象属于那个类,可以用__class__特性
- >>> s.__class__
- <class __main__.SPAMFilter at 0x00000000029E2F48>

 

多个超类:

- >>> class Calculator:
-         def calculator(self,expression):
-             self.value = eval(expression)
- >>> class Talker:
-         def talk(self):
-             print "Hi,my value is:", self.value
- >>> class TalkingCalculator(Calculator,Talker):
-         pass

#子类不做任何事,从超类中继承所有的方法,从Calculator中继承calculator方法.

从Talker中继承talk的方法.这种行为成为多种继承

- >>> TC = TalkingCalculator()
- >>> TC.calculator('1+2*3')
- >>> TC.talk()
- Hi,my value is: 7
  1.  

Note: 除非对超类特别熟悉,否则尽量避免使用,以免出现不可预知的错误.

 

接口和内省

接口的概念与多态有关。在处理多态对象时,只要关心它的接口即可-也就是公开的方法和特性.

Python,不用显式指定对象必须包含哪些方法才能做为参数接收。

一般来说,只需要让对象实现当前方法即可。 可用hasattr()来检查方法是否已经存在

- >>> class Calculator:
-     def calculator(self,expression):
-             self.value = eval(expression)
- >>> class Talker:
-     def talk(self):
-         print "Hi,my value is:", self.value
- >>> class TalkingCalculator(Calculator,Talker):
-         pass

- >>> tc = TalkingCalculator()
>>> hasattr(tc,'talk')
True
>>> hasattr(tc,'fnord')
False

如果有需要的话,甚至还可以检查talk是否可调用:

>>> callable(getattr(tc,'talk'))
True
>>> callable(getattr(tc,'fnord',None))
False

与getattr相对应的是setattr

>>> setattr(tc,'name','Mr. Smith')
>>> tc.name
'Mr. Smith'

Note: callable函数在Python3.0不再使用,取而代之的是hasattr(x,'__call__')

 

本章函数

callable(object)                          确定对象是否可调用(比如函数或方法)

getattr(object,name[,default])            确定特性的值,可选择提供默认值

hasattr(object,name)                      确定对象是否有给定的特性

isinstance(object,class)                  确定对象是否是类的实例

issubclass(A,B)                           确定A是否是B的子类

random.choice(sequence)                   从非空序列中随机选择元素

setattr(object,name,value)                设定对象的给定特定为value

type(object)                              返回对象的类型

打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Day7-人生苦短我学python

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!