python 面向对象

python面向对象

1.面向对象的定义

面向对象实质是一种编程框架结构,只要使用类编程就是面向对象编程,这种说法是有问题的。

使用函数也可以做到面向对象编程

def school(name,addr,type):
    def init(name, addr, type):
        sch = {
            'name': name,
            'addr': addr,
            'type': type,
            'kao_shi': kao_shi,
            'zhao_sheng': zhao_sheng,
        }
        return sch
    def kao_shi(school):
        print('%s 学校正在考试' %school['name'])
    def zhao_sheng(school):
        print('%s %s 正在招生' %(school['type'],school['name']))
    return  init(name,addr,type)

s1=school('oldboy','沙河','私立学校')
print(s1)
print(s1['name'])

s1['zhao_sheng'](s1)

s2=school('清华','北京','公立学校')

print(s2)
print(s2['name'],s2['addr'],s2['type'])
s2['zhao_sheng'](s2)

Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法

Object 对象 
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同

Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法

Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承

Polymorphism 多态

一个接口,多种实现

2.类的创建

#用面向对象编程独有的语法class去实现面向对象设计
class Dog:
    def __init__(self,name,gender,type):
        self.name=name
        self.gender=gender
        self.type=type

    def bark(self):
        print('一条名字为[%s]的[%s],狂吠不止' %(self.name,self.type))

    def yao_ren(self):
        print('[%s]正在咬人' %(self.name))

    def chi_shi(self):
        print('[%s]正在吃屎' %(self.type))


dog1=Dog('alex','female','京巴')

3.面向对象的继承

class Dad:
    '这个是爸爸类'
    money=10
    def __init__(self,name):
        print('爸爸')
        self.name=name
    def hit_son(self):
        print('%s 正在打儿子' %self.name)

class Son(Dad):
    money = 1000000000009
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def hit_son(self):
        print('来自儿子类')

继承的循序

#coding:utf-8
class A:
    # def test(self):
    #     print('A')
    pass
class B(A):
    # def test(self):
    #     print('B')

    pass
class C(A):
    # def test(self):
    #     print('C')
    pass

class D(B):
    # def test(self):
    #     print('D')
    pass

class E(C):
    # def test(self):
    #     print('E')
    pass

class F(D,E):
    # def test(self):
    #     print('F')
    pass
f1=F()
f1.test()   #经典类:F->D->B->A-->E-->

# print(F.__mro__)

#F-->D->B-->E--->C--->A新式类

4.接口继承

import abc
class All_file(metaclass=abc.ABCMeta):      ##不能被实例化
    @abc.abstractmethod
    def read(self):               #被abc.abstractmethod 修饰的方法必须被复写,不然会报错
        pass

    @abc.abstractmethod
    def write(self):
        pass

class Disk(All_file):
    def read(self):                 
        print('disk read')

    def write(self):
        print('disk write')

class Cdrom(All_file):
    def read(self):
        print('cdrom read')

    def write(self):
        print('cdrom write')


class Mem(All_file):
    def read(self):
        print('mem read')

    def write(self):
        print('mem write')
#
m1=Mem()
m1.read()
m1.write()

5.类的组合

class school(object):
    def __init__(self,name,addr,course):
        self.name=name
        self.addr=addr
        self.course=course
    def zhao(self):
        print('%s可以找1000人' %self.name)
class course(object):
    def __init__(self,name,period):
        self._name=name
        self.period=period
    def start(self):
        print('%s 开课了' %self.name)
c1=course('英语','10')
s=school('beida','beij',c1)
print(s.__dict__)

6.类的反射

class People:
    country = 'china'

    def __init__(self,name,age):
        self.name = name
        self.age = age

    def talk(self):
        print('%s is talking' % self.name)

obj=People('egon',18)
# print(obj.name)
# print(obj.talk)

# hasattr
print(hasattr(obj,'name')) #obj.name #obj.__dict__['name']
print(hasattr(obj,'talk'))


# getattr
print(getattr(obj,'namexxx',None))
print(getattr(obj,'talk',None))

# setattr
setattr(obj,'sex','male')
print(obj.sex)


# delattr
delattr(obj,'age')
print(obj.__dict__)

7.动态导入模块

第一种python内部使用,不建议使用
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author:CarsonLi
'''Python 解释器内部动态导入方式'''
module_name='import_lib.metaclass' #模块名的字符串
import_lib=__import__(module_name) #这是解释器自己内部用的
'''import_lib代表的其实是这个模块,而不是下面的metaclass'''
 
c=import_lib.metaclass.Ccc("Bert")#调用下面的方法
print(c.name) #运行结果:Bert

第二种 官方建议使用
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author:CarsonLi
'''官方建议用这个'''
import importlib
module_name='import_lib.metaclass' #模块名的字符串
metaclass=importlib.import_module(module_name) #导入的就是需要导入的那个metaclass
c=metaclass.Ccc("Bert") #调用下面的方法
print(c.name)  #运行结果:Bert

8.双下划线的attr方法

只有在属性不存在时会自动触发__getattr__

删除属性是会触发__delattr__

设置属性是会触发__setattr__

 

class Foo:
    def __init__(self,name):
        self.name=name
    def __getattr__(self, item):
        print('你找的属性【%s】不存在' %item)
    def __setattr__(self, k,v):
        print('执行setattr',k,v)
        if type(v) is str:
            print('开始设置')
            # self.k=v #触发__setattr__
            self.__dict__[k]=v.upper()
        else:
            print('必须是字符串类型')
    def __delattr__(self, item):
        print('不允许删除属性【%s】' %item)
        # print('执行delattr',item)
        # del self.item
        # self.__dict__.pop(item)

f1=Foo('alex')
# f1.age=18 #触发__setattr__
# print(f1.__dict__)
# print(f1.name)
# print(f1.age)
# print(f1.gender)
# print(f1.slary)
print(f1.__dict__)
del f1.name
print(f1.__dict__)

9.授权

可以读某些内建方法改写,并添加权限管理

import time
class FileHandle(object):
    def __init__(self,filename,mode='r',encoding='utf-8'):
        # self.filename=filename
        self.file=open(filename,mode,encoding=encoding)
        self.mode=mode
        self.encoding=encoding
    def write(self,line):
        print('------------>',line)
        t=time.strftime('%Y-%m-%d %X')
        self.file.write('%s %s' %(t,line))

    def __getattr__(self, item):
        # print(item,type(item))
        # self.file.read
        return getattr(self.file,item)

f1=FileHandle('a.txt','w+')
# print(f1.file)
# print(f1.__dict__)
# print('==>',f1.read) #触发__getattr__
# print(f1.write)
f1.write('1111111111111111\n')
f1.write('cpu负载过高\n')
f1.write('内存剩余不足\n')
f1.write('硬盘剩余不足\n')
# f1.seek(0)
# print('--->',f1.read())

10.__call__方法

 类中实现了__call__方法,则对应的实例可以被调用。

class Foo:
    def __call__(self, *args, **kwargs):
        print('实例执行啦 obj()')

f1=Foo()

f1() #f1的类Foo 下的__call__

Foo() #Foo的类 xxx下的__call__

11.item系列方法

__getitem__、__setitem__  、__delitem__ 相对于__setattr__ 、__getattr__ 、__delattr__

使用[ ]方式调用字典,而attr系列是使用‘.’方式调用底层字典的

class Foo(object):
    def __getitem__(self, item):
        print('getitem',item)
        return self.__dict__[item]

    def __setitem__(self, key, value):
        print('setitem')
        self.__dict__[key]=value

    def __delitem__(self, key):
        print('delitem')
        self.__dict__.pop(key)

f1=Foo()
print(f1.__dict__)
# f1.name='egon'  #---->setattr-------->f1.__dict__['name']='egon'
f1['name']='egon'#--->setitem--------->f1.__dict__['name']='egon'
f1['age']=18

print('===>',f1.__dict__)

# del f1.name
# print(f1.__dict__)
#
# print(f1.age)
del f1['name']
print(f1.__dict__)

print(f1['age'])
raise S

12.__slots__方法

这个方法定义是可以节省内存的,试想一下一个类实例化很多对象,每个对象都有一个底层的字典,自然会很占用内存

。使用__slots__方法的类,是没有底层字典的。

另外__slots__是无法被继承的

class Foo(object):
    __slots__=['name','age']  #{'name':None,'age':None}
    # __slots__='name' #{'name':None,'age':None}

f1=Foo()
# f1.name='egon'
# print(f1.name)

# f1.age=18  #--->setattr----->f1.__dict__['age']=18

# print(f1.__dict__)
print(Foo.__slots__)
print(f1.__slots__)
f1.name='egon'
f1.age=17
print(f1.name)
print(f1.age)
# f1.gender='male'


f2=Foo()
print(f2.__slots__)
f2.name='alex'
f2.age=18
print(f2.name)

13.迭代器协议

迭代器的实质是实现了next()方法的对象,常见的元组、列表、字典都是迭代器。

迭代器中重点关注两种方法:

__iter__方法:返回迭代器自身。可以通过python内建函数iter()调用。

__next__方法:当next方法被调用的时候,迭代器会返回它的下一个值,如果next方法被调用,但迭代器没有只可以返回,就会引发一个StopIteration异常。该方法可以通过 python 内建函数next()调用。 

举例

class Foo(object):
    def __init__(self,n):
        self.n=n
    def __iter__(self):
        return self

    def __next__(self):                ####注 python2中使用的是next()方法
        if self.n == 13:
            raise StopIteration('终止了')
        self.n+=1
        return self.n

# l=list('hello')
# for i in l:
#     print(i)
f1=Foo(10)
# print(f1.__next__())
# print(f1.__next__())
# print(f1.__next__())
# print(f1.__next__())

for i in f1:  # obj=iter(f1)------------>f1.__iter__()
     print(i)  #obj.__next_()

 

14.__format__

###自定制format格式
format_dic={
    'ymd':'{0.year}{0.mon}{0.day}',
    'm-d-y':'{0.mon}-{0.day}-{0.year}',
    'y:m:d':'{0.year}:{0.mon}:{0.day}'
}
class Date:
    def __init__(self,year,mon,day):
        self.year=year
        self.mon=mon
        self.day=day
    def __format__(self, format_spec):
        print('我执行啦')
        print('--->',format_spec)
        if not format_spec or format_spec not in format_dic:
            format_spec='ymd'
        fm=format_dic[format_spec]
        return fm.format(self)
d1=Date(2016,12,26)
# format(d1) #d1.__format__()
# print(format(d1))
print(format(d1,'ymd'))
print(format(d1,'y:m:d'))
print(format(d1,'m-d-y'))
print(format(d1,'m-d:y'))
print('===========>',format(d1,'asdfasdfsadfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd'))

15.上下文管理协议

with obj as  f:
    '代码块'
    
1.with obj ----》触发obj.__enter__(),拿到返回值

2.as f----->f=返回值、

3.with obj as f  等同于     f=obj.__enter__()

4.执行代码块
一:没有异常的情况下,整个代码块运行完毕后去触发__exit__,它的三个参数都为None
二:有异常的情况下,从异常出现的位置直接触发__exit__
    a:如果__exit__的返回值为True,代表吞掉了异常
    b:如果__exit__的返回值不为True,代表吐出了异常
    c:__exit__的的运行完毕就代表了整个with语句的执行完毕

class Foo:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('执行enter')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('执行exit')
        print(exc_type)
        print(exc_val)
        print(exc_tb)
        return True
with Foo('a.txt') as f:
    print(f)
    print(asdfsaasdfasdfasdfasdfasfasdfasdfasdfasdfasfdasfd)  #触发__exit__
    print(f.name)
    print('-----------------')
    print('-----------------')
    print('-----------------')
    print('-----------------')
    print('-----------------')
    print('-----------------')
    print('-----------------')
print('000000000000000000000000000000000000000000000')

16.__getattr__和__getattribute__的区别

object.__getattr__(self, name) 
找不到attribute的时候,会调用getattr,返回一个值或AttributeError异常。 

object.__getattribute__(self, name) 
无条件被调用,通过实例访问属性。如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常)

 

(1)调用一个不存在的属性

class User:
    def __init__(self,info={}):
        self.info = info

    # def __getattr__(self, item):
    #     return self.info[item]

if __name__ == '__main__':
    user = User(info={"name":"derek","age":24})
    print(user.name)

(2)加了__getattr__之后就可以调用了

class User:
    def __init__(self,info={}):
        self.info = info

    #__getattr__是在查找不到属性的时候调用
    def __getattr__(self, item):
        return self.info[item]

if __name__ == '__main__':
    user = User(info={"name":"derek","age":24})
    print(user.name)    #derek

(3)__getattribute__

class User:
    def __init__(self,info={}):
        self.info = info

    #__getattr__是在查找不到属性的时候调用
    def __getattr__(self, item):
        return self.info[item]

    #__getattribute不管属性存不存在,都访问这个
    def __getattribute__(self, item):
        return "zhang_derek"


if __name__ == '__main__':
    user = User(info={"name":"derek","age":24})
    #不管属性存不存在,都走__getattribute__
    print(user.name)    #zhang_derek     #即使属性存在也走__getattribute__
    print(user.test)     #zhang_derek    #不存在的属性也能打印
    print(user.company)   #zhang_derek   #不存在的属性也能打印

17.__new__和__init__的区别

(1)__new__方法如果不返回对象,不会执行init方法

class User:
    def __new__(cls, *args, **kwargs):
        print("in new")

    def __init__(self,name):
        print("in init")
        self.name = name

# new是用用来控制对象的生成过程,在对象生成之前
# init是用来完善对象的
# 如果new方法不返回对象,则不会调用init函数
if __name__ == '__main__':
    user = User("derek")

运行结果:没有调用init方法

 (2)返回对象就会执行init方法

class User:
    def __new__(cls, *args, **kwargs):
        print("in new")         #in new
        print(cls)              #cls是当前class对象    <class '__main__.User'>
        print(type(cls))        #<class 'type'>
        return super().__new__(cls)   #必须返回class对象,才会调用__init__方法

    def __init__(self,name):
        print("in init")        #in init
        print(self)             #self是class的实例对象      <__main__.User object at 0x00000000021B8780>
        print(type(self))       #<class '__main__.User'>
        self.name = name

# new是用用来控制对象的生成过程,在对象生成之前
# init是用来完善对象的
# 如果new方法不返回对象,则不会调用init函数
if __name__ == '__main__':
    user = User(name="derek")

#总结
# __new__ 用来创建实例,在返回的实例上执行__init__,如果不返回实例那么__init__将不会执行
# __init__ 用来初始化实例,设置属性什么的

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值