『python学习』Python核心编程——面向对象编程

来源:互联网 发布:js限制ip访问代码 编辑:程序博客网 时间:2024/04/28 22:23

1、属性是属于另一个对象的数据或者函数元素(即类方法)

2、有关属性的一个有趣的地方是,当你正访问一个属性时,它同时也是一个对象,拥有它自己的属性,可以访问

>>> class Test(object):        def test(self):            pass>>> mytest = Test()>>> mytest.test()>>> mytest.test().__class__<type 'NoneType'>

3、类属性仅与其被定义的类相绑定


4、类数据属性仅当需要有更加“静态”数据类型时才变得有用

我的理解是:就如同函数参数设置的默认值,在调用函数的时候可以传递非默认值,但如果不是作为函数参数,而是在函数内赋值时,则无法改变。


5、数据属性仅仅是所定义的类的变量


6、静态变量或静态数据:这些数据是与它们的所属的类对象绑定的,不依赖于任何类实例

>>> class C(object):        foo = 100>>> print C.foo100>>> C.foo = C.foo + 1>>> C.foo101

>>> c = C()>>> c.foo101>>> c.foo = c.foo + 1>>> c.foo102>>> C.foo101

第二种情况体现的是类变量的查找顺序问题,即优先查找当前实例,然后才是类的成员变量


7、为与 OOP 惯例保持一致, Python 严格要求,没有实例,方法是不能被调用的。这种限制即 Python 所描述的绑定概念(binding),在此,方法必须绑定(到一个实例)才能直接被调用


8、所谓的绑定即是类的实例化。非绑定如果要被调用,那么实例对象一定要明确给出,才能确保调用成功

MyClass.myNoActionMethod(MyClass())


9、__name__ 是给定类的字符名字,它适用于那种只需要字符串(类对象名字),而非类对象本身的情况。


10、在定义类的 __del__() "解构器"方法时,要调用父类的解构器方法

class C(P):    def __del__(self):        P.__del__(self)

11、不要在 __del__() 中干与实例没有任何关系的事


12、__init__() 应当返回 None


13、实例仅有两个特殊属性:

I.__class__ :实例化 I 的类

I.__dict__ :I 的属性


14、实例的 __dict__ 属性由一个字典组成,字典中仅有实例属性,没有类属性或特殊属性

在使用时仅能这样使用:实例名.__dict__ ,而不能这样使用:实例名.__dict__() ,这样使用的话会报错


15、可以通过如下的方法修改 __dict__ ,因为其本质上就是一个字典

c.__dict__["test"] = "test"
但一般还是通过句点属性标识来访问及操作属性会更易于接受,如:

c.foo = 1 c.bar = "SPAM"

16、尽管 __dict__ 属性是可修改的,但还是建议你不要修改这些字典,除非你知道你的目的,因为这些修改可能会破环你的 OOP,造成不可预料的副作用。


17、内建类型也是类


18、如果我们知道了一个复数由什么样的属性,我们就可以访问它的数据属性,调用它的方法了:

x = 3 + 0.14jprint x.__class__dir(x)print [type(getattr(x, i)) for i in ("conjugate", "imag", "real")]print x.imagprint x.realprint x.conjugate


19、如果试着访问 __dict__ 会失败,因为在内建类型中,不存在这个属性


20、类属性仅是与类相关的数据值,和实例属性不同,类属性和实例无关

21、你可采用类来访问类属性,如果实例没有同名的属性的话,你也可以用实例来访问

class C(object):    test1 = 1     test2 = 10 c = C()c.test1 = 100print c.test1print c.test2

22、当 C() 实例化为 c 时,如果改变 c 的属性时,不会改变 C() 的属性;如果 C() 中的属性被改变了,而 c 中没有定义同名的属性时,则 c 调用该属性时则是该属性被改变后的结果,如 test2

class C(object):    test1 = 1     test2 = 10 c = C()c.test1 += 10 print c.test1print C.test1C.test1 += 100print c.test1print C.test1C.test2 += 111print c.test2print C.test2


如何理解该特性呢?我们可以理解为 Python 在我们创建实例时,为我们创建了一个实例空间,而同时还创建了类空间(也有可能这个类空间在我们创建实例时就已经存在了)

而在访问实例属性时遵循了先访问实例空间后类空间的原则,故如果在实例空间中定义了某属性,则只访问实例空间的该属性,而不访问类空间的同一属性(也可理解为把类空间的同一属性屏蔽了) 而如果实例空间没有定义该属性,则再去访问类空间的同一属性,而如果此时的类空间中也没有该属性,则会报错


23、修改类属性需要使用类名,而不是实例名


24、可以动态地为类添加新的属性,如为 22 中的 C() 类添加新的 test3 属性

C.test3 = 100


25、任何一个方法定义中的第一个参数都是变量 self ,它表示调用此方法的实例对象


26、

①. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,产生了一个super对象;
②. super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
③. super(B, self).func的调用并不是用于调用当前类的父类的func函数;
④. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用super);
⑤. 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次。


27、静态方法仅是类中的函数,不需要实例


28、类的组合

假设我们有 NewAddrBookEntry、Name、Phone 三个类,则如果我们可以对这三个类进行组合,如在前者中创建后两者的实例

class NewAddrBookEntry(object):    def __init__(self, nm, ph):        self.name = Name(nm)    # 创建 Name 实例        self.phome = Phome(ph)    # 创建 Phone 实例

29、子类可以调用父类的方法,但父类不可以调用子类的方法

如果子类中没有跟被调用的父类的同名的方法,则可以直接调用,如 c.parentMethod()

但是如果是同名的情况下,则需要将 c 换成其父类的类名,如 Parent ,同时将 c 传递进去,如 Parent.test(c)

class Parent(object):    def parentMethod(self):        print "calling parent method"            def test(self):        print "我是Parent.test"class Child(Parent):    def childMethod(self):        print "calling child method"            def test(self):        print "我是 child.test"


30、文档字符串对类、函数/方法,还有模块来说都是唯一的,所以特殊属性 __doc__ 不会从基类中继承过来


31、hasattr() 、getattr() 、setattr() 、delattr()

在操作 obj.attr 时,就相当于调用 *attr(obj, "attr"....) 系列函数

hasattr() 函数是 Boolean 型的,它的目的是为了决定一个对象是否有一个特定的属性,一般用于某属性前先作一下检查。


getattr() 和 setattr() 函数相应地取得和赋值给对象的属性,getattr() 会在你试图读取一个不存在的属性时,引发 AttributeError 异常,除非给出那个可选的默认参数。 setattr() 将要么加入一个新的属性,要么取代一个已存在的属性

注:当使用 getattr() 来取得对象的方法(函数)时,会返回该对象的引用而不会调用它,如果需要调用,则需要加上 (),如:getattr(t, "test")()

但取得的是数据属性时则会直接返回数据对象

delattr() 函数会从一个对象中删除属性


32、dir() 作用在实例上时,显示实例变量,还有在实例所在的类及所有它的基类中定义的方法和类属性

dir() 作用在类上时,则显示类以及它的所有基类的 __dict__ 中的内容,但它不会显示定义在元类中的类属性

dir() 作用在模块上时,则显示模块的 __dict__ 的内容

dir() 不带参数时,则显示调用者的局部变量


33、每个类都有一个名为 __mro__ 的属性,它是一个元组,按照他们被搜索时的顺序,列出了被搜索的类

注: MRO: 文档解释顺序


34、如果在子类中要调用父类的方法,最简便的方法是:super(subclass, self).attr() ,其中 attr() 正是我们要调用的属性


35、vars() 内建函数与 dir() 相似,只是给定的对象参数都必须有一个 __dict__ 属性,vars() 返回一个字典,它包含了对象存储于其 __dict__ 中的属性(键) 及值


36、vars() 与 dir() 并不等同,vars(Test) 与 vars(Test()) 也并不等同,但 dir(Test) 与 dir(Test()) 也并不等同

class Test:    passt = Test()print vars(Test)print vars(Test())print dir(Test)print dir(Test())-------------------------{'__module__': '__main__', '__doc__': None}{}['__doc__', '__module__']['__doc__', '__module__']

37、


0 0
原创粉丝点击