天天看点

python 学习笔记——类

在函数前面加双下划线使函数为私有,私有类只有类的内部访问,实例不能访问私有函数,同样私有函数不能被继承

函数的参数当参数有默认值时,该参数后面的所有参数都必须有默认值

当父类实现了构造函数__init__()时,如果子类也要实现构造函数,则必须显示调用父类的构造函数,如果不显示调用父类的构造函数,则父类的构造函数将要被覆盖

显示调用父类的构造函数有两种方式:BaseClass.__init__(self,*args)   ; super(subclass,self).__init__()

:例如

(声明:此处将__init__()称为构造函数,不是很合规范)

class Baseclass():
    GLOBAL = None

    def __init__(self):
        pass

    def a(self):
        print self.GLOBAL


class SubClass(Baseclass):
    GLOBAL = 1

    def __init__(self):
        Baseclass.__init__(self)   #这里需要自己手动显示调用父类的__init__() 函数   还可以用super(Subclass,self).__init__()
         <pre name="code" class="python" style="font-size: 11.8181819915771px;"><span style="white-space:pre">	</span># super(Subclass,self).__init__()  这样用的话当改变了继承关系就不需要在这里像上面一样需要改基类的名称
           

def subdef(self): self.a()

__dict__:返回类的属性的一个字典,实例调用返回实例的变量属性,而当类名来调用时返回类的所有属性

dir(): 返回类的属性的一个列表(只有属性名)【此函数时根据其域进行执行,用在函数中是列出函数内部的属性,用在类中是列出类的属性,用在全局中列出全局的属性】

__name__:返回类的名字,需要className.__name__  调用,而不是实例进行调用,实例调用会出错

__bases__:返回类的所有父类的元组,不包括父类的父类

class supersuperclass():
    pass

class superclass(supersuperclass):
    """
    super comment
    """
    def __init__(self):
        self.a = 1
        self.n = 2

    def aa(self):
        pass

    def __aa(self):
        pass


class buildin(superclass, supersuperclass):
    """
    subclass comment here
    """
    subclass1 = 1

    def __init__(self):
        superclass.__init__(self)
        self.subaa = 2
        self.subnn = 3

    def buildin(self):
        """
        def comment
        :return:
        """
        # print '__name__', self.__name__    # buildin instance has no attribute '__name__',self相当于是类的实例,所有调用会出错
        print '__doc__', self.__doc__
        # print 'bases', self.__bases__        #  buildin instance has no attribute '__bases__',同理
        print '__dict__', self.__dict__


subclasstest = buildin()
subclasstest.buildin()
print __name__
# print __bases__

print dir(subclasstest)
print subclasstest.__dict__
print buildin.__dict__            #注意和上一行代码的不同以及输出结果的不同
print buildin.__bases__
print buildin.__name__
# print subclasstest.__name__     # AttributeError: buildin instance has no attribute '__name__'
# print subclasstest.__bases__    # 同理



输出结果为:
__doc__ 
    subclass comment here
    
__dict__ {'a': 1, 'subnn': 3, 'subaa': 2, 'n': 2}
__main__
['__doc__', '__init__', '__module__', '_superclass__aa', 'a', 'aa', 'buildin', 'n', 'subaa', 'subclass1', 'subnn']
{'a': 1, 'subnn': 3, 'subaa': 2, 'n': 2}
{'buildin': <function buildin at 0x7f36de955410>, '__module__': '__main__', 'subclass1': 1, '__doc__': '\n    subclass comment here\n    ', '__init__': <function __init__ at 0x7f36de955398>}
(<class __main__.superclass at 0x7f36de939c18>, <class __main__.supersuperclass at 0x7f36de939bb0>)
buildin
           

python 类的实例会在一个属于该实例的命名空间内进行运作

对于类的静态变量,当实例化出一个实例的时候,静态变量只属于该实例的命名空间,只有该实例和类名访问静态变量时才能修改这个静态变量的值

class C():
    version = 1
    def pri(self):
        print self.version


class D(C):
    version = 9999


c = C()
d = D()
print c.version     # output: 1
c.pri()             # output: 1
print C.version     # output: 1
print d.version     # output: 9999
d.pri()             # output: 9999
                    # D()继承C() 覆盖了C中的version 所以在调用d.pri()函数时整个类的命名空间中version值为9999,所以这里输出的是9999
                    # d实例的命名空间包括C(),D()的命名空间
print '\n\n\n'
C.version = 2
print C.version     # 2
print c.version     # 2  当通过类访问静态变量并改变静态变量的值时,对应的实例中此变量也会改变
print d.version     # 9999   但不会影响其子类中此变量的值
print '\n\n\n'
c.version = 3
print C.version     # 2 通过实例改变静态变量的值时,不会影响通过类对应的命名空间中的值
print c.version     # 3
print d.version     # 9999
print '\n\n\n'
d.version = 4
print C.version     # 2
print c.version     # 3
print d.version     # 4
print D.version     # 9999
print '\n\n\n'
D.version = 5
print C.version     # 2
print c.version     # 3
print d.version     # 4  当前面通过实例 d 修改过静态变量时,此处就修改不了了,当实例改变了变量值时,该静态变量就只在该实例的命名空间里存在了,当尝试在实例中更新类属性时,会创建一个实例属性d.version,这会阻止对类属性D.version的访问
print D.version     # 5


           
</pre></p><p><pre name="code" class="python">class C():
    version = 1
    def pri(self):
        print self.version

class D(C):
    version = 9999

c = C()
d = D()
print c.version     # output: 1
c.pri()             # output: 1
print C.version     # output: 1
print d.version     # output: 9999
d.pri()             # output: 9999
                    # D()继承C() 覆盖了C中的version 所以在调用d.pri()函数时整个类的命名空间中version值为9999
                    # d实例的命名空间包括C(),D()的命名空间
print '\n\n\n'
C.version = 2
print C.version     # 2
print c.version     # 2  当通过类访问静态变量并改变静态变量的值时,对应的实例中此变量也会改变
print d.version     # 9999   但不会影响其子类中此变量的值
print '\n\n\n'
c.version = 3
print C.version     # 2 通过实例改变静态变量的值时,不会影响通过类对应的命名空间中的值
print c.version     # 3
print d.version     # 9999
print '\n\n\n'
D.version = 5
print C.version     # 2
print c.version     # 3
print d.version     # 5  这和上面的又不一样,当没有通过实例去修改静态变量的时候通过类名去改变静态变量时,实例中此静态变量也会改变
print D.version     # 5