博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

http://www.liaoxuefeng.com/ python 类

Posted on 2015-12-02 21:41  bw_0927  阅读(197)  评论(0)    收藏  举报

在Python中,定义类是通过class关键字:

class Student(object):
    pass

class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的。

 

和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。

 

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),__xxx,只有内部可以访问,外部不能访问.

 

需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name____score__这样的变量名。

 

有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

 

双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:

>>> bart._Student__name
'Bart Simpson'

 

静态语言 vs 动态语言

对于静态语言(例如Java,c++)来说,如果需要传入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()方法的对象。

 

在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,len()函数内部,它自动去调用该对象的__len__()方法,所以,下面的代码是等价的:

>>> len('ABC')
3
>>> 'ABC'.__len__()
3

我们自己写的类,如果也想用len(myObj)的话,就自己写一个__len__()方法

 

built-in function getattr/setattr/hasattr in module __builtin__

 

在Python这类动态语言中,根据鸭子类型,有read()方法,不代表该fp对象就是一个文件流,它也可能是网络流,也可能是内存中的一个字节流

 

在编写程序的时候,千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。

class Student(object):
    def __init__(self, name):
        self.name = name      //实例属性
s = Student('Bob')
print s.name //实例属性
print Student.name //AttributeError: type object 'Student' has no attribute 'name',没有类属性


class Student(object):
    name = 'Student'        //类属性

 

类变量/类属性(相当于c++中的类静态变量)访问方式:
类名.类变量


类成员变量访问方式:
实例.类成员变量

 

在 Python 中,类的基类只是简单地列在类名后面的小括号里。所以 FileInfo 类是从 UserDict 类继承来的。
Python 支持多重继承。在类名后面的小括号中,你可以列出许多你想要的类名,以逗号分隔。
__init__ 在类的实例创建后被立即调用。每个类方法的第一个参数,包括 __init__,都是指向类的当前实例的引用。按照习惯这个参数总是被称为 self。
当定义方法时你需要明确指定 self,但在调用方法时,你不 用指定它,Python 会替你自动加上的。但 self 在 Python 中并不是一个保留字,它只是一个命名习惯。
C++中父类的构造函数在子类构造方法中会被自动调用。但Python 不是这样,你必须在__init__方法中显示地调用在父类中的__init__方法
__init__ 方法从不返回一个值。
__init__ 方法是可选的,但是一旦你定义了,就必须记得显示调用父类的__init__ 方法 (如果它定义了的话)。

在 Python 中,创建类的实例只要调用一个类,仿佛它是一个函数就行了。不像 C++ 或 Java 有一个明确的 new 操作符。

每一个类的实例有一个内置属性,__class__,它是对象的类。  成员函数的self参数指向类的当前实例的引用

#!/bin/python

class Test(object) :
        def __init__(self):
                print 'construct'

        def __del__(self):
                class_name = self.__class__.__name__
                print class_name, "destoryed"

if __name__ == '__main__':
        t = Test()
        del t

  

 

 

=================

属性分为实例属性与类属性

方法分为普通方法,类方法,静态方法

 

一:属性:

  尽量把需要用户传入的属性作为实例属性,而把同类都一样的属性作为类属性。实例属性在每创造一个实例时都会初始化一遍,不同的实例的实例属性可能不同,不同实例的类属性都相同。从而减少内存

  1:实例属性:

    最好在__init__(self,...)中初始化

    内部调用时都需要加上self.

    外部调用时用instancename.propertyname

  2:类属性:

    在__init__()外初始化

    在内部用classname.类属性名调用,即使在__init__中访问类属性,也得用类名.类属性的方式来访问

    外部既可以用classname.类属性名又可以用instancename.类属性名来调用

  3:私有属性:

    1):单下划线_开头:只是告诉别人这是私有属性,外部依然可以访问更改

    2):双下划线__开头:外部不可通过instancename.propertyname来访问或者更改

      实际将其转化为了_classname__propertyname

二:方法

  1:普通类方法:

    def fun_name(self,...):

      pass

    外部用实例调用

  2:静态方法:@staticmethod            

      不能访问实例属性!!!   参数不能传入self!!!

      与类相关但是不依赖类与实例的方法!!

  3:类方法:@classmethod

      不能访问实例属性!!!   参数必须传入cls!!!

      必须传入cls参数(即代表了此类对象-----区别------self代表实例对象),并且用此来调用类属性:cls.类属性名

  *静态方法与类方法都可以通过类或者实例来调用。其两个的特点都是不能够调用实例属性

  

  e.g1:

  1. class A:  
  2.     member = "this is a test."  
  3.     def __init__(self):  
  4.         pass  
  5.  
  6.     @classmethod  
  7.     def Print1(cls):  
  8.         print "print 1: ", cls.member  
  9.           
  10.     def Print2(self):  
  11.         print "print 2: ", self.member  
  12.             
  13.          
  14.     @classmethod      
  15.     def Print3(paraTest):  
  16.         print "print 3: ", paraTest.member  
  17.     @staticmethod  
  18.     def print4():  
  19.         print "hello"  

 

总结:类属性与类方法是类固有的方法与属性,不会因为实例不同而改变,写他们的目的是减少多实例时所创造出来的内存空间,加快运行速度。