Python基础知识

静态方法和类方法:

静态方法和实例方法的区别主要体现在两个方面:
1. 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
3. 类方法可以被对象调用,也可以被实例调用;传入的都是类对象,主要用于工厂方法,具体的实现就交给子类处理
4. 静态方法参数没有实例参数 self, 也就不能调用实例参数
 
 
  1. # coding: utf-8  
  2. class Fruit(object):  
  3.     version = 1.0  #静态对象  
  4.     """docstring for Fruit"""  
  5.     def __init__(self):  
  6.         super(Fruit, self).__init__()  
  7.         self.color = 'blue'  
  8.   
  9.     def is_clean(cls):  
  10.         print cls.color  
  11.         return True  
  12.  
  13.     @classmethod  
  14.     def foo(cls):  
  15.         #类方法可以被对象调用,也可以被实例调用;传入的都是类对象,主要用于工厂方法,具体的实现就交给子类处理  
  16.         Fruit.version += 1  
  17.         print cls.color  
  18.         print 'calling this method foo()'  
  19.  
  20.     @staticmethod  
  21.     def pish_color(color):  
  22.         #静态方法参数没有实例参数 self, 也就不能调用实例参数  
  23.         Fruit.color = color  
  24.   
  25.     def add_foo(self):  
  26.         Fruit.version += 1  
  27.   
  28.   
  29.   
  30. if __name__ == "__main__":  
  31.     o = Fruit()  
  32.     o.is_clean()  
  33.     # o.pish_color('Green')  
  34.     # o.foo()  
  35.     Fruit.foo()  
  36.     # o.add_foo()  
  37.     # print o.version  
  38.     # o.foo()  
  39.     # print o.version  
  40.     # print Fruit.version  




__init__与 __new__:

__init__ 方法是什么?

使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候。例如:

# -*- coding: utf-8 -*-

class Person(object):

  """Silly Person"""

  def __init__(self, name, age):

    self.name = name

    self.age = age

  def __str__(self):

    return '<Person: %s(%s)>' % (self.name, self.age)

if __name__ == '__main__':

  piglei = Person('piglei', 24)

  print piglei

这样便是__init__最普通的用法了。但__init__其实不是实例化一个类的时候第一个被调用 的方法。当使用 Persion(name, age) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__ 方法。

__new__ 方法是什么?

__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。

# -*- coding: utf-8 -*-

class Person(object):

  """Silly Person"""

  def __new__(cls, name, age):

    print '__new__ called.'

    return super(Person, cls).__new__(cls, name, age)

  def __init__(self, name, age):

    print '__init__ called.'

    self.name = name

    self.age = age

  def __str__(self):

    return '<Person: %s(%s)>' % (self.name, self.age)

if __name__ == '__main__':

  piglei = Person('piglei', 24)

  print piglei

执行结果:

piglei@macbook-pro:blog$ python new_and_init.py

__new__ called.

__init__ called.

<Person: piglei(24)>

通过运行这段代码,我们可以看到,__new__方法的调用是发生在__init__之前的。其实当 你实例化一个类的时候,具体的执行逻辑是这样的:

1.p = Person(name, age)

2.首先执行使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例(通常情况下是使用 super(Persion, cls).__new__(cls, ... ...) 这样的方式)

3.然后利用这个实例来调用类的__init__方法,上一步里面__new__产生的实例也就是 __init__里面的的 self

所以,__init__ 和 __new__ 最主要的区别在于:

1.__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。

2.__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。

但是说了这么多,__new__最通常的用法是什么呢,我们什么时候需要__new__?

__new__ 的作用

依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。

首先我们来看一下第一个功能,具体我们可以用int来作为一个例子:

假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。

class PositiveInteger(int):

  def __init__(self, value):

    super(PositiveInteger, self).__init__(self, abs(value))

i = PositiveInteger(-3)

print i

但运行后会发现,结果根本不是我们想的那样,我们任然得到了-3。这是因为对于int这种 不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用。

这是修改后的代码:

class PositiveInteger(int):

  def __new__(cls, value):

    return super(PositiveInteger, cls).__new__(cls, abs(value))

i = PositiveInteger(-3)

print i

通过重载__new__方法,我们实现了需要的功能。

另外一个作用,关于自定义metaclass。其实我最早接触__new__的时候,就是因为需要自定义 metaclass,但鉴于篇幅原因,我们下次再来讲python中的metaclass和__new__的关系。

用__new__来实现单例

事实上,当我们理解了__new__方法后,我们还可以利用它来做一些其他有趣的事情,比如实现 设计模式中的 单例模式(singleton) 。

因为类每一次实例化后产生的过程都是通过__new__来控制的,所以通过重载__new__方法,我们 可以很简单的实现单例模式。

class Singleton(object):

  def __new__(cls):

    # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象

    if not hasattr(cls, 'instance'):

      cls.instance = super(Singleton, cls).__new__(cls)

    return cls.instance

obj1 = Singleton()

obj2 = Singleton()

obj1.attr1 = 'value1'

print obj1.attr1, obj2.attr1

print obj1 is obj2

输出结果:

value1 value1

True

可以看到obj1和obj2是同一个实例。




Python小知识点

a. python里所有对象可以动态地添加新的属性,当类动态地添加属性后,类的实例都能访问到该对象,其实这个很好理解,动态语言,只要遵循一定的解析规则就行
b. 类里的变量不是以self,开头定义的都是类变量,相当于java,c++里的static,所有实例共享他们
c.函数都是实现为descriptor
d.每个实例有__dict__用来存放动态的属性
e.继承:当继承后,python不会向java,c++那样在子类的实例中包含父类的实例,子类的实例是个全新的对象,与父类一点关系都没有,不会包含有父类的任何东西,继承只是在子类的__base__指向了父类,在查找函数,属性的过程中会查找父类,仅此而已,而这个父类也是class对象

---------------

descriptor
python所有的函数都是descriptor,当通过实例访问函数时,descriptor将self插入参数列表,并且调用这个函数。

--------------------------------

python中,使用字典从中取出数据的时候,最好先用has_key判断一下字典中是否有要取的元素。因为如果直接_dict['key']的话,如果key不在字典中则会报错。






新式类和旧式类

python的新式类是2.2版本引进来的,我们可以将之前的类叫做经典类或者旧类。

为什么要在2.2中引进new style class呢?官方给的解释是:

为了统一类(class)和类型(type)。

在2.2之前,比如2.1版本中,类和类型是不同的,如a是ClassA的一个实例,那么a.__class__返回 ‘ class    __main__.ClassA‘ ,type(a)返回总是<type 'instance'>。而引入新类后,比如ClassB是个新类,b是ClassB的实例,b.__class__和type(b)都是返回‘class '__main__.ClassB' ,这样就统一了。

引入新类后,还有其他的好处,比如更多的内置属性将会引入,描述符的引入,属性可以来计算等等。

为了向前兼容,默认情况下用户定义的类为经典类,新类需要继承自所有类的基类 object 或者继承自object的新类。

值得注意的地方是,虽然使用的是最新的python(2.7),但是一些特性不会在旧式类起作用。
所以,为了确保自己使用的是新式类,有以下方法:

  1. 把这个赋值语句放在类模块代码的最前面 __metaclass__ = type(前面有提过)。

  2. 自己的类都从内建类object直接或者间接地继承。

如果不需要兼容旧式类,旧版本的类,那么就保持都是新式类。
当然,在Python3里面,不存在这些问题了,因为所有的类都是object类的子类(隐式)。


代码示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class  CC:             #经典类
     def  __init__(  self  ):
         pass
 
class  CCN( object ):     #新类
     def  __init__(  self  ):
         pass 
 
c1  =  CC()
c2  =  CCN()
 
c1.__class__             # 输出-> <class __main__.CC at 0x0137BF10>
type (c1)                 # 输出-> <type 'instance'>
 
c2.__class__             # 输出-><class '__main__.CCN'>
type (c2)                 # 输出-><class '__main__.CCN'>
 
dir (c1)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值