面向对象

1.如何创建类

class deadalus:
    pass

通过上述的创建方法中,可以看出关键词是class。并且与函数不同的是类名后面没有加括号。

2.如何创建方法

def 方法名(self,a,b):
    print(self,a,b)
    return a,b

首先方法其实就是类中的函数。所以创建方式还是与之前相同,也可以在函数中传入一些参数,但是第一个参数必须是self。

2.1普通方法

构造方法

    def __init__(self,name,age):    
        print("gaga")

构造方法也是一个函数,不同的地方是在对象被创建的时候就会自动执行这个函数就会被执行。其功能就像是在对象被创建的时候就有几个参数需要被传入。这些传入的参数存

储的位置也是在对象内,不在class中。

普通方法

def func1(self,a,b):
    print(self,a,b)
    return a,b

普通方法是相对于构造方法才有的。它的调用必须通过class

创建一个对象

类和类下的方法有了,下面代码展示了如何调用这些方法:

obj = deadalus("ccc",18)

obj.func1(3,4)

将一个括号加在类后面赋给一个变量,这个变量就是对象。这个过程中实现的有两个动作。1:创建obj这个对象2:执行init函数。这也是为什么deadalus后面有参数。

2.2静态方法

   @staticmethod
    def func():              
        print("static")

静态方法是不需要通过对象就能直接调用的方法。与一般的函数没什么区别。方式为daedalus.func()

2.3类方法

@classmethod             
def clamd(cls):
    print(cls)

类方法是一个特殊的方法,它不需要传参数。默认的参数就是类名。

2.3__call__方法

    def __call__(self, *args, **kwargs):
        print("call")

类方法后面加括号是执行init方法,当对象后面加括号时表示只有__call__方法被执行。

2.4str和int方法

    def __str__(self):
        pass
    def __int__(self):
        pass

str和int函数是当执行str()或者int()执行的函数,两者本身也是一个类。print(对象名)会自动执行其中str函数。

2.5列表索引方法

 def __getitem__(self, item): 
        return self.a1,self.b1
 def __setitem__(self, key, value):
        print(key,value)
 def __delitem__(self, key):
        print(key)

上述的三个方法分别对应的是索引,索引赋值,删除。即对象名[0],对象名[0]="c",del 对象名[0]当这三个操作被执行时执行对应的方法。若是没有对应方法会报错。

2.6字段

    普通字段

    def __init__(self,name,age):     
        print("gaga")
        self.mingzi = name           
        self.nianling = age          

上述代码中self.mingzi = name 就是普通字段,其实就讲这个类的参数用一个变量接受下来。这里的self就是对象。所以对象在创建的时候也在对象本身内存储了两个变量。

    静态字段

静态字段如同静态函数一样,是class本身的变量。通过类点变量的方式可以直接用。注意:对象与类关联,说明通过对象也可以调用修改class的静态字段。

3.面向对象的特性

  3.1封装

封装是一个过程,在上面的操作中一直有使用到。将传过数据的变量封装到对象内存中。这个过程就是封装。

  3.2继承

在创建class的过程中,其实可以加括号,并且括号里面必须是一个或多个其他类。创建的这个类就是子类或者叫基类。括号里面的类就叫做它的父类或者派生类。

 1 class base:
 2     pass
 3 class you2:
 4     def you2_1(self):
 5         self.gue()
 6     def gue(self):
 7         print("you2")
 8 class you1(you2):
 9     pass
10 class zuo:
11     def gue(self):
12         print("zuo")
13 class son(zuo,you1):
14     print('main')

上述的son这个类就继承了多个父类,而且父类也是其他函数的子类。

所以这里有:

a = son(1,2)
a .you2_1()

结果是

main

zuo

同时执行

若是在子类中有func函数父类中也有func函数并且都想要执行。在子类func中加入其中一句话:

super(son,self).func1() 

foo.func(self)

子类自动继承父类的所有函数,和init函数。所以若是父类中需要参数的传入子类中不需要,但是在对象创建的过程中也要传入参数。

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

上面这句话是对现象的片面分析后的错误总结,正确的思考应该是:

子类集成父类的函数。init函数在一个对象中只会有一个执行!!!所以应该根据寻找顺序找到第一个构造函数进行传参数。

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

  寻找顺序

在上述的代码中我们运行一下的代码:

a = son()

a.you_2()

结果为:

main

zuo

这个结果说明了继承的顺序:由左到右,一条道到黑。若是有节点最后一条再走。

a.you_2()这个结果则说明了self这个字眼完全就是对象本身。尽管在you2这个函数中也有gue这个函数,它还是返回了对象开始寻找。

补充

多继承顺序是一个很复杂的问题,实际应用中应该避免循环多继承。参考 http://www.cnblogs.com/khal-Cgg/p/5897434.html

  3.3多肽

Python这个语言本身就是多肽的。传参数的函数中,一个a既可以是字符串也可以字典等。 

 4.属性的用法

 1 class dfed:
 2     def __init__(self,page):
 3         self.page = page
 4     @property  # 属性
 5     def start(self):
 6         val = (self.page - 1) * 10
 7         return val
 8 
 9     @property  # 属性
10     def end(self):
11         val = self.page * 10
12         return val
13 
14 listd = []
15 for i in range(1000):
16     listd.append(i)
17 while True:
18     page = input(">>>")
19     suan = dfed(page)
20     print(listd[suan.start:suan.end])

从这个函数中稍微体现了属性蛋疼的用法。即去括号:是的suan.start看起来成为了一个字段。

5.析构函数和私有方法,私有属性。

 1 class start():
 2     def __init__(self,a,b):
 3         self.name = a
 4         self.__age = b
 5     def func1(self):
 6         print("func1")
 7     def __func2(self):
 8         print(__age) 9     def __del__(self):
10         print("This is the end")
11 r1 = start("ccc",23)
12 r1.func1()
13 s = r1.name
14 print(s)
15 r2 = start("ccc",23)
16 r2.func1()

func1
ccc
func1
This is the end
This is the end

其中del就是析构函数,它在释放r1之后会马上执行。但是在这里this is the end是跟在了r2的结果后面。因为r1是在程序结束后才被释放。主动的del r1会让析构马上执行。

age就是私有(实例)属性外边r1调用会报错。但是在func2中可以调用。

同理私有方法func2也是如此。

5.attr

在s2模块中有两个函数:

def f1():
    print("homepage")
def f2():
    print("news")

若是在s1中调用时有:

import s2
while True:
    inp = input(">>>")
    if hasattr(s2,inp):
        r = getattr(s2,inp)
        r()
    else:
        print("404")

这里可以看到hasattr和getattr的作用。has即是判断的意思,get即是拿到这个内容(方法,属性,变量等)。与普通调用不同是这次利用是用户输入字符串的方法。

还有另一个setattr同理设置变量。

6.单例模式

第一种:

class Singleton(object):
	__instance=None
	def__init__(self):
		pass
	def__new__(cls,*args,**kwd):
		if Singleton.__instance is None:
			Singleton.__instance=object.__new__(cls,*args,**kwd)
		return Singleton.__instance

第二种

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            orig = super(Singleton,cls)
            cls._instance =  orig.__new__(cls)
        return cls._instance

将需要单例的类继承这个类即可

7.异常处理

try:
    a = int("w2")
    raise Exception         # 主动出发这个异常
except ValueError as e:     # 若是执行错误就执行print
    print(e)
except IndexError as e:    误
    print(e)
except Exception as e:
    print(e)
else:
    print("正确")            # 否则(正确的情况下)执行
finally:
    print("处理完成")

异常处理的作用就是当程序出错后结束之前捕获到错误,并进行处理。

try:之后缩进的内容一旦有出错马上截止并执行except后的内容。valueerror是错误中的一种。若被valuaerror捕获到就执行print若不是这个类型的错误,则继续判断下一个。。。直到exception会捕获所有的错误。else表示若是没有捕获到任何错误则执行。finally表示无论如何都会执行。

assert 1==1判断条件是否成立,不成立直接报错。一般不用捕获。

原文地址:https://www.cnblogs.com/khal-Cgg/p/5895907.html