Python面向对象

1.面向对象的定义

  面向对象,即将函数(方法)进行分类和封装。

  创建对象:

 1 #class 是创建类的关键字,People 是类名
 2 class People:
 3     #定义一个方法即函数
 4     def get_name(self,name):
 5         print(name)
 6 
 7 nanren = People()  # 创建一个对象nanren
 8 nanren.get_name('男人')  # 男人
 9 nvren = People()   # 创建一个对象nvren
10 nanren.get_name('女人')  # 女人    

2.面向对象的三个特性

  1)封装

    将公用的字段放在__init__(self)中,类中的其他方法可以调用,也称构造方法。

 1 class People:
 2     #构造方法,将接受到的fname和lname进行保存
 3     # self 就是创建的对象名称
 4     def __init__(self,fname,lname):
 5         self.fname = fname
 6         self.lname = lname
 7 
 8     # get_fullname(self)称为自定义方法
 9     def get_fullname(self):
10         full_name = self.fname + self.lname
11         print(full_name)
12 
13 obj = People('slito','bo') # 创建对象时类传递的参数就是__init__中定义的形参
14 obj.get_fullname() # slitobo

  2)继承

    任何派生类(子类)都继承基类(父类)的内容。  

#定义一个父类father
class father:
    def f1(self):
        print('f1.test')
    def f2(self):
        print('f2.test')

#定义一个类son,继承father
class son(father):
    def s1(self):
        print('hello son')

# 定义一个子类的对象obj_son1,该对象可以访问父类father中的方法。
obj_son1 = son()
obj_son1.f1() # f1.test
obj_son1.f2() # f2.test

  在子类的方法中执行父类的方法。

class son(father):
    def s1(self):
        print('hello son')
    def s2(self):
        super(son,self).f2() # 第一种方法
        # father.f2(self)   # 第二种方法
obj_son1 = son()
obj_son1.s2() # f2.test

  多继承

  一个类可以继承多个父类。当不同的类中有相同的方法时,根据相应的查找顺序查找。

  查找顺序分为: 深度查找和广度查找。

  深度查找:执行obj.bar()后,先找D,D中没有找B,B中没有,找到A,A中没有,再找C。找到任何一个先停止。

                  

class A:
    def bar(self):
        print('A')
class B(A):
    pass
class C:
    def bar(self):
        print('C')
class D(B, C):
    pass

obj = D()
obj.bar() # A

  广度查找:执行obj.bar()后,先找D,D中没有找B,B中没有,再找C,C中没有,再找A。找到任何一个先停止。

                   

class A:
    def bar(self):
        print('A')
class B(A):
    pass
class C(A):
    def bar(self):
        print('C')
class D(B, C):
    pass

obj = D()
obj.bar() # C

     总结:1)左侧优先查找,一路查到底,找到则停止。

        2)相同根,广度查找,最后找根。

  3)多态

    同一种事物(类)有多种状态,如动物又分为,人,猪,狗等。

    多态以继承为基础。   

class Animals:
    def run():
        print("子类可以使用我")

class people(Animals):
    def run():
        print("我可以直立行走和使用语言")

class pig(Animals):
    def run():
        print("我能睡")

    多态性

      一种执行方式,不同执行效果。    

def func(obj):
    obj.run()
func(peo1) #执行效果一
func(pig1) #执行效果二
func(d1) #执行效果三

3.面向对象的类成员

                          

  1)字段

    普通字段 & 静态字段

    静态字段存放在类中,节省内存。对象使用字段会浪费内存。

      如果不使用静态字段country,则需要在每个对象调用getname方法时,传入“中国”,则“中国”会占用对象的内存。

class provice:
    country = '中国'  # 静态字段
    # name是普通字段
    def getname(self,name):
        print(self.country,name)

obj = provice()
obj.getname('陕西') # 中国 陕西
obj.getname('浙江') # 中国 浙江

  2)方法

    普通方法 & 静态方法 & 类方法   

class provice:
    country = '中国'  # 静态字段
    # 普通方法
    def getname(self,name):
        print(self.country,name)
# 静态方法,不需要self,和普通函数一样 @staticmethod def getstatic(): print('static')
# 类方法,cls = 类名 @classmethod def getclass(cls): print(cls) print(cls.country) obj = provice() obj.getstatic() # static obj.getclass() # <class '__main__.provice'> # 中国

  3)属性

  @property 此装饰器将方法调用变成字段调用的方式

class foo:
    @property
    def get_name(self):
        print('属性测试')
obj = foo()
# obj.get_name() # TypeError: 'NoneType' object is not callable
obj.get_name # 属性测试

  方法.setter/deleter(仅作一一对应)

class foo:
    @property
    def get_name(self):
        print('属性测试')
    @get_name.setter
    def get_name(self,val):
        print(val)
    @get_name.deleter
    def get_name(self):
        print('deleter')
obj = foo()
obj.get_name # 属性测试
obj.get_name = 123 # 123
del obj.get_name # deleter

4.面向对象的特殊方法

  1)__doc__  类的描述信息   

class Foo:
    ''' 类的描述'''
    def func(self):
        pass

print (Foo.__doc__) # 类的描述
View Code

  2)__module__ 对象属于那个模块

from lei import foo
obj = foo()
print(obj.__module__) # lei
View Code

  3)__class__ 操作对象的类是哪一个

from lei import foo
obj = foo()
print(obj.__class__) # lei.foo
View Code

  4)__call__ 对象加括号执行__call__中定义的内容

class foo:
    def __call__(self, *args, **kwargs):
        print('call test')
obj = foo()
obj() # call test
View Code

  5)__dict__ 将构造方法中定义的变量与创建对象的时给的值,生成字典。

class foo:
    def __init__(self,name,age):
        self.name1 = name
        self.age1= age
obj = foo('slitobo','27')
print(obj.__dict__) # {'name1': 'slitobo', 'age1': '27'}
View Code

   6)__str__ 将__str__方法中的返回值(字符串)返回给对象

 1 class car:
 2     def __init__(self,color,sign):
 3         self.color = color
 4         self.sign = sign
 5     def __str__(self):
 6         msg = "这是一辆"+self.color+""+self.sign
 7         return msg
 8 
 9 dazhong = car("白色","大众")
10 print(dazhong) # 这是一辆白色的大众

  7)__getitem__/__setitem__/__delitem__  处理KEY-VALUE类型的数据,对对象进行获取/设置/删除key的操作时,引用这三个方法。

 1 class Foo():
 2 
 3     def __getitem__(self, key):
 4         print('__getitem__', key)
 5 
 6     def __setitem__(self, key, value):
 7         print('__setitem__', key, value)
 8 
 9     def __delitem__(self, key):
10         print('__delitem__', key)
11 
12 obj = Foo()
13 
14 result = obj['k1'] # __getitem__ k1
15 obj['k2'] = 'test' # __setitem__ k2 test
16 del obj['k1']      # __delitem__ k1

  8)__iter__ ,该方法的返回值为可迭代对象,对象 = 返回值 ,与iter()函数一样的效果

 1 class foo:
 2     def __init__(self,list1):
 3         self.list1 = list1
 4     def __iter__(self):
 5         return  iter(self.list1)
 6 list1=[1,2,3,4]
 7 obj = foo(list1)
 8 for i in obj:
 9     print(i,end=" ") # 1 2 3 4 
10 # 函数iter()的效果
11 # list1=[1,2,3,4]
12 # it = iter(list1)
13 # for i in it:
14 #     print(i,end=" ")  # 1 2 3 4 
View Code

  9)__add__,将两个对象的进行处理,如数字相加/减,字符串组合

 1 class foo:
 2     def __init__(self,name,age):
 3         self.name = name
 4         self.age = age
 5     def __add__(self, other):
 6         return self.age + other.age
 7 obj = foo('slito',10)
 8 obj2 = foo('slito1',20)
 9 obj3 = obj + obj2
10 print(obj3)  # 30
View Code

  * 10)metaclass 和__new__ (还有点疑问)

  在之前,创建一个对象,使用"对象=类名()"这种方法创建。进行详解说明创建一个对象的过程。

  metaclass :用在类中的方法,表示该类是由谁来创建,默认是由type创建。

#class foo(metaclass=type): #默认
class foo():
    pass
print(type(foo)) # <class 'type'>

  __new__:是在类准备将自身实例化时调用,创建对象。

  定义一个类,继承type类,模拟创建实例的过程。

 1 class mytype(type):
 2     def __init__(self,what,bases=None,dict=None):
 3         super(mytype,self).__init__(what,bases,dict)
 4 
 5     def __call__(self, *args, **kwargs):
 6         obj = self.__new__(self, *args, **kwargs)
 7         self.__init__(obj)
 8 
 9 #object是所有新式类的基类
10 class foo(object):
11     __metaclass__ = mytype
12     def __init__(self):
13         pass
14     def __new__(cls, *args, **kwargs):
15         return object.__new__(cls, *args, **kwargs)
16 
17 #obj1 是foo的实例化
18 obj1 = foo()
19 print(obj1) # __main__.foo object at 0x000001CEDE1D2748>

   过程说明:

    第一步,foo()执行时,由于metaclass是mytype,则由mytype类创建foo类,此时"类名()"调用了__call__()方法,其中self是foo。

    第二步,指定foo中的__new__()方法,将类实例化,返回一个值,该值就是foo实例化后的对象。

    第三步,由一个变量obj接受上面的返回值,执行self.__init__(obj),self是foo,执行foo中的__init__方法,将obj赋给参数self。

5.异常处理

  对可能发生报错的语句块进行捕获处理

  如int(num)时,num是数值型则不会报错,如果是num是字符串,则发生Value error

num = input('请输入一个数字:')
try:
    num = int(num)
except Exception as e:
    print('输入有误,请输入数字')
else :
    print(num)
finally:
    print('The end')

  try 中的语句块可能会报错。如果报错,则执行except 中的语句块。没有报错,则执行else中的语句。最后都要执行finally语句块。

  其中,Exception是捕获所有的错误, 将捕获的错误信息放到e中(e可随便取名称)


  自定义异常捕获和主动触发异常
  raise 可以主动生成异常。 

# 定义一个slitoboerror类,继承Exception
class slitoerror(Exception):
    def __init__(self,msg):
        self.message = msg
    #类实例化后返回值为字符串
    def __str__(self):
        return self.message

try:
    # 主动触发异常
    raise slitoerror('iamwrong')
except slitoerror as e:
    print(type(e)) # <class '__main__.slitoerror'>
    print(e) # iamwrong 

6.单例模式

    节省内存,创建的多个对象使用同一块内存。

  使用场景如数据库连接。应用程序与数据库要建立一个连接池,连接池就是一个类,每个连接都是一个对象或者实例。

class foo:
    __instance = None

    def __init__(self):
        self.dbhost = '1.1.1.1'
        self.port = 3306
        self.username = 'mysql'
        self.pw = 'mysql'
    @classmethod
    def get_single_instance(cls):
        if cls.__instance:
            return cls.__instance
        else:
            cls.__instance = foo()
            return cls.__instance

    def chaxun(self):
        #登录mysql
        pass

mysql_intsance1 = foo.get_single_instance()
mysql_intsance2 = foo.get_single_instance()
print(mysql_intsance1) # <__main__.foo object at 0x0000019AFEF127F0>
print(mysql_intsance2) # <__main__.foo object at 0x0000019AFEF127F0>

mysql_intsance1.chaxun()
mysql_intsance2.chaxun()
View Code

 

                         

7.反射

  反射是通过字符串形式获取对象中字段或者方法。

  hasattr()/getattr()/setattr()/delattr()

class foo:
    country = 'china'
    def getname(self,name):
        print(name)
obj = foo()

   hasattr(o,name) 判断对象中是否存在该名称,存在返回值为True,不在返回值为False

result = hasattr(obj,'country')
print(result) # True
result = hasattr(obj,'abc')
print(result) # False

   getattr(o,name[,default]) 获取对象中的名称的值,存在就返回当前值,不存在如果有默认值就返回默认值,没有默认值报错。如果获取的是方法,则获取的是方法的内存地址。

#获取字段
c = getattr(obj,'country',None)
print(c) # china
#获取方法
fun = getattr(obj,'getname')
print(fun) # <bound method foo.getname of <__main__.foo object at 0x0000021D125826D8>>
fun('slitobo') # slitobo

    setattr(o,name,value) 设置对象中,name = value,name存在则修改。

setattr(obj,'province','zhejiang')
c = getattr(obj,'province',None)
print(c) # zhejiang

    delattr(o,name) 删除对象中name

delattr(obj,'province')
c = getattr(obj,'province',None)
print(c) # None

 

posted @ 2018-07-12 16:09  slitobo  阅读(191)  评论(0)    收藏  举报