python 面向对象

面向对象设计(Object oriented design):将一类具体事物的数据和动作整合到一起,即面向对象设计

 

面向对象编程(object-oriented programming):用定义类+实例/对象的方式去实现面向对象的设计

 

 

1. 类和对象

1.什么叫类:类是一种数据结构,就好比一个模型,该模型用来表述一类事物(事物即数据和动作的结合体),用它来生产真实的物体(实例)。

2.什么叫对象:睁开眼,你看到的一切的事物都是一个个的对象,你可以把对象理解为一个具体的事物(事物即数据和动作的结合体)

(铅笔是对象,人是对象,房子是对象,狗是对象,alex是对象,配齐是对象,元昊是对象)

3.类与对象的关系:对象都是由类产生的,上帝造人,上帝首先有一个造人的模板,这个模板即人的类,然后上帝根据类的定义来生产一个个的人

4.什么叫实例化:由类生产对象的过程叫实例化,类实例化的结果就是一个对象,或者叫做一个实例(实例=对象)

 

类是用来描述一类事物,类的对象指的是这一类事物中的一个个体

是事物就要有属性,属性分为

1:数据属性:就是变量

2:函数属性:就是函数,在面向对象里通常称为方法

注意:类和对象均用点来访问自己的属性

 

类的函数属性还没有传参数

#注意:类和对象均用点来访问自己的属性

class Chinese:
    "这个一个中国人的类"
    dang = "***"             #类的数据属性:就是变量
    def sui_di_tu_tan():       #类的函数属性:就是函数,在面向对象里通常称为方法
        print("吐了一口痰")

    def cha_dui(self):         #函数属性:就是函数,在面向对象里通常称为方法
        print("插到了前面")

print(Chinese.dang)
Chinese.sui_di_tu_tan()
Chinese.cha_dui("先随便传一个参数")

print("---------------")

#类名.__dict__:查出的是一个字典,key为属性名,value为属性值
print(Chinese.__dict__["dang"])        # __dict__ 里面存的是Chinese 的属性字典
Chinese.__dict__["sui_di_tu_tan"]()    # 可以通过 __dict__ 里面的key调用Chinese的属性
Chinese.__dict__["cha_dui"]("先随便传一个参数")

 

类和对象

 #def __init__(self,name,age,gender): #实例化的过程可以简单理解为执行该函数的过程,实例本身会当作参数传递给self(这是默认的步骤)
class Chinese:
    "这个一个中国人的类"
    dang = "***"              #类的数据属性:就是变量

    def __init__(self,name,age,gender):   #实例的数据属性
        self.mingzi = name
        self.nl = age
        self.xb = gender

    def sui_di_tu_tan(self):       #类的函数属性:就是函数,在面向对象里通常称为方法
        print("%s %s %s 吐了一口痰"%(self.mingzi,self.nl,self.xb))

    def cha_dui(self):         #类的函数属性:就是函数,在面向对象里通常称为方法
        print("%s 插到了前面"%self.mingzi)


p1 = Chinese("tom",18,"男")    #实例化  创建一个对象p1

print(p1.mingzi,p1.nl,p1.xb)    #打印实例的数据属性

print(p1.__dict__)    # __dict__ 里面存的是p1 的属性字典
print(p1.dang)   #先在实例(对象)的__init__的数据属性里找,找不到就找类的数据属性

p1.sui_di_tu_tan()   #类的函数属性,会自动把p1传给self

p1.cha_dui()    #类的函数属性,会自动把p1传给self

 

类的增删改查

class Chinese:
    councry = "china"

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

    def paly_ball(self,ball):
        print("%s 正在打 %s"%(self.name,ball))

#查看类的数据属性
print(Chinese.councry)

#修改类的数据属性
Chinese.councry = "Japan"
print(Chinese.councry)

# 实例化 创建一个对象
p1 = Chinese("tom")
print(p1.__dict__)

#增加类的数据属性
Chinese.dang = "***"
print(Chinese.dang)

#删除类的数据属性
del Chinese.dang

# 增加类的函数属性
def eat_foot(self,foot):
    print("%s 正在吃 %s"%(self.name,foot))

Chinese.eat = eat_foot    # 增加类的函数属性
p1.eat("屎")


# 对象调用类的函数属性
p1.paly_ball("篮球")

# 修改类的函数属性
def test(self):
    print("test")

Chinese.paly_ball = test   #修改类的函数属性
p1.paly_ball()

 

对象的增删改查

class Chinese:
    councry = "china"

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

    def paly_ball(self,ball):
        print("%s 正在打 %s"%(self.name,ball))


p1 = Chinese("tom")   #实例化 创建对象
print(p1.__dict__)    #查看实例的数据属性

#查看实例的数据属性
print(p1.name)

#增加实例的数据属性
p1.age = 18
print(p1.__dict__)

#删除实例的数据属性
del p1.age
print(p1.__dict__)

#修改实例的数据属性
p1.name = "liaoboshi"
print(p1.__dict__)

 

特殊的类属性

class ChinesePeople:
    '我们都是中国人,我们骄傲的活着,我们不服任何事和物'
    government='***'
    def sui_di_tu_tan():
        print('90%的中国人都喜欢随地吐痰')

    def cha_dui(self):
        print('一个中国人-->%s<--插到了前面' %self)

print(ChinesePeople.__name__)# 类C的名字(字符串)
print(ChinesePeople.__doc__)# 类C的文档字符串
print(ChinesePeople.__base__)# 类C的第一个父类(在讲继承时会讲)
print(ChinesePeople.__bases__)# 类C的所有父类构成的元组(在讲继承时会讲)
print(ChinesePeople.__dict__)# 类C的属性
print(ChinesePeople.__module__)# 类C定义所在的模块
print(ChinesePeople.__class__)# 实例C对应的类(仅新式类中)

 

静态属性

class Room:
    def __init__(self,name,owner,le,wight,heigh):
        self.name = name
        self.owner = owner
        self.le = le
        self.wight = wight
        self.heigh = heigh

    @property     # 静态属性     把函数属性伪装成数据属性
    def cal_dz(self):
        return (self.le*self.wight*self.heigh)*0.5

r = Room("房间","tom",2,2,2)
print(r.cal_dz)

 

静态方法

class Room:
    tag = 1
    def __init__(self,name,owner):
        self.name = name
        self.owner = owner

    @staticmethod       #静态方法
    def wash_body(a,b,c):
        print("洗----->",a,b,c)

Room.wash_body(1,2,3)       #类可以使用
r = Room("房间","tom")
r.wash_body(1,2,3)          #实例也可以使用

 

类方法

class Room:
    tag = 1
    def __init__(self,name,owner):
        self.name = name
        self.owner = owner

    @classmethod         # 类方法  专门给类使用,与实例无关  类方法只能访问类相关的属性,不能访问实例属性(与实例无关)
    def tell_info(cls):
        print(cls)
        print("----->",cls.tag)


Room.tell_info()

 

 

组合

class School:
    def __init__(self,name,addr):
        self.name = name
        self.addr = addr

    def zhao_sheng(self):
        print("%s %s 正在招生"%(self.addr,self.name))


class Course:
    def __init__(self,name,price,period,school):
        self.name = name
        self.price =price
        self.period = period
        self.school = school


s1 = School("oldboy","北京校区")
s2 = School("oldboy","深圳校区")
s3 = School("oldboy","广州校区")

c = Course("python",15800,"5M",s2)    #把学校的实例传进去
print(c.__dict__)             # 输出 实例c 的属性字典
c.school.zhao_sheng()         # 执行 实例s2 的zhao_sheng 函数属性

 

 

继承 

class Dad:
    money = 10
    def __init__(self,name):
        print("------Dad------")
        self.name = name

    def hit_son(self):
        print("%s 正在打son"%self.name)


class Son(Dad):
    money = 10000




s = Son("tom")                       # 实例Son的类,Son类中没有__init__方法,会调父类中的__init__方法,并且要传父类中要的参数
print(s.money)  #===>10000           # 查看Son类的money属性 ,没有会找父类的
s.hit_son()  #===>tom 正在打son      # 调用Son类的hit_son方法,没有会找父类的

print(Dad.money) #===>10            # 子类和父类都有money的属性,子属的money属性不会覆盖父类的

 

接口继承

import abc

class All_file(metaclass = abc.ABCMeta):
    @abc.abstractmethod           #子类要实例化,必须定义用@abc.abstractmethod 修饰的方法
    def read(self):
        pass

    @abc.abstractmethod
    def writ(self):
        pass


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

    def writ(self):
        print("disd writ")

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

    def writ(self):
        print("mem writ")

m = Mem()       #想要实例,Mem类必须定义父类用@abc.abstractmethod修饰的方法
m.read()
m.writ()

 

继承顺序

class A:
    def test(self):
        print("A")

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


f = F()
f.test()                          # 继承顺序有 深度优先和广度优先
print("F的继承顺序",F.__mro__)     # python3 的继承顺序是广度优先

 

在子类中调用父类的属性和方法(super方法的使用)

class Vehicle:
    councry = "china"
    def __init__(self,name,speed,load,power):
        self.name = name
        self.speed = speed
        self.load = load
        self.power = power

    def run(self):
        print("开动了")
        print("开动了")
        print("开动了")

class Subway(Vehicle):
    def __init__(self,name,speed,load,power,line):
        # Vehicle.__init__(self,name,speed,load,power)     #调用父类的__init__方法,不用再初始化一次
        super().__init__(name,speed,load,power)            #调用父类的__init__方法,不用再初始化一次
        self.line = line

    def test(self):
        print(self.name,self.speed,self.load,self.power,self.line)

    def run(self):
        # Vehicle.run(self)        # 可以运行子类与父类相同的 run 方法  不会只运行子类的 run 方法
        super().run()               # 可以运行子类与父类相同的 run 方法  不会只运行子类的 run 方法
        print(" %s 开动了"%self.name)


s = Subway("北京地铁","100km/h",500,"电",13)     #实例s 
s.test()           #通过实例s调用Subway的方法
s.run()            #通过实例s调用子类和父类的run方法

 

多态

#类的继承有两层意义:1.改变 2.扩展
#多态就是类的这两层意义的一个具体的实现机制
#即,调用不同的类实例化得对象下的相同的方法,实现的过程不一样

#python中的标准类型就是多态概念的一个很好的示范

class H2o:
    def __init__(self,name,wd):
        self.name = name
        self.wd = wd

    def turn_ice(self):
        if self.wd < 0 :
            print("%s 温度小于0变冰了"%self.name)
        elif self.wd >0 and self.wd <100:
            print("%s 液化成水了"%self.name)
        elif self.wd >100 :
            print("%s 温度太高变水蒸气了"%self.name)

class S(H2o):
    pass

class Ice(H2o):
    pass

class Szq(H2o):
    pass


s = S("水",20)
i = Ice("冰",-20)
sz = Szq("水蒸气",120)

def func(obj):
    obj.turn_ice()

func(s)
func(i)
func(sz)

 

封装

class People:
    star = "地球"
    def __init__(self,id,name,age):
        self.name = name
        self.id = id
        self.age = age

p = People("231243","tom",18)
print(p.star)


class People:
    _star = "地球11111"
    def __init__(self,id,name,age):
        self.name = name
        self.id = id
        self.age = age

p = People("231243","tom",18)
print(p._star)     # _属性名  的属性不建议在外面使用



class People:
    __star = "地球222222"    #  __属性名  python 用自动重命名为 _类名__属性名   __属性名  的属性不建议在外面使用
    def __init__(self,id,name,age):
        self.name = name
        self.id = id
        self.age = age

p = People("231243","tom",18)
print(People.__dict__)
print(p._People__star)    #  __属性名  python 用自动重命名为 _类名__属性名,如果通过 __属性名 会报错

 

包装标准类型

class List(list):

    def append(self, p_object):     #修改类List(list父类基础上)的append方法
        if type(p_object) is str:   #只能添加字符串
            super().append(p_object)
        else:
            print("只能加字符串")

    # def min(self):     # 在列表类的基础上加了一个可以查到列表中间元素的方法
    #     i = int(len(self)/2)
    #     return self[i]

l = List("helloworld")
print(l)

# print(l.min())   #查看中间元素

l.append("tom")
print(l)

 

反射

class Heizj():
    def __init__(self,name,addr):
        self.name = name
        self.addr = addr

    def sell_house(self):
        print("%s 正在卖房子"%self.name)

h = Heizj("万盛置地","天露园")
print(hasattr(h,"name"))     #检测对象是否有这个属性

#获取对象属性
print(getattr(h,"name"))     #获取对象属性
a = getattr(h,"sell_house")
a()             #
# print(getattr(h,"fjdiohg"))   #获取对象属性,没有这个属性就报错
print(getattr(h,"fjdiohg","123"))    #获取对象属性,没有这个属性不报错,会输出第三个参数

setattr(h,"sb","tom")    #设置属性,没有这个属性就添加到属性字典里
setattr(h,"name","456")  #设置属性,有这个属性,就修改这个属性
print(h.__dict__)        #查看属性

delattr(h,"sb")      #删除属性
# delattr(h,"fas")   #删除属性,没有就报错
print(h.__dict__)    #查看属性

 

双下划线attr方法系列

class Foo:
    x = 1
    def __init__(self,y):
        self.y = y

    def __getattr__(self, item):
        print("__getattr__运行了")

f = Foo(10)
print(f.x)
f.sssssssss   #运行的属性 当类里没有的时候 就自动会运行__getattr__方法


class Foo:
    x = 1
    def __init__(self,y):
        self.y = y

    def __delattr__(self, item):
        print("__delattr__运行了")

f = Foo(10)
del f.x        #一有删除操作就会运行__delattr__方法
del f.y


class Foo:
    x = 1
    def __init__(self,y):
        self.y = y

    def __setattr__(self, key, value):
        print("__setattr__运行了")
        # self.key = value
        self.__dict__["key"] = value   #设置属性的时候会自动调用__setattr__, 上一行会无限递归,直接设置__dict__不会

f = Foo(10)
print(f.__dict__)
f.z = 5
print(f.__dict__)

双下划线item方法系列

# 触发双下划线item系列,要调用 f1["name"] ,就是要通过中括号去调用才会触发
# 触发双下划线attr系列,要调用 f1.name ,就是要 点 去调用用才会触发

class Foo():
    def __getitem__(self, item):
        print("__getitem__")
        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 = "tom"

#__setitem__
f1["name"] = "tom"
f1["age"] = 18
print("=====>",f1.__dict__)

#__delitem__
del f1["name"]
print(f1.__dict__)

#__getitem__
print(f1["age"])

 

 

授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。

实现授权的关键点就是覆盖__getattr__方法

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

    def __getattr__(self, item):
        return getattr(self.file,item)

f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read())
f1.close()

#授权示范一

 

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#我们来加上b模式支持
import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        if 'b' in mode:
            self.file=open(filename,mode)
        else:
            self.file=open(filename,mode,encoding=encoding)
        self.encoding=encoding

    def write(self,line):
        t=time.strftime('%Y-%m-%d %T')
        if 'b' in self.mode:
            msg=bytes('%s %s' %(t,line),encoding=self.encoding)
        self.file.write(msg)

    def __getattr__(self, item):
        return getattr(self.file,item)

f1=FileHandle('b.txt','wb')
f1.write('你好啊啊啊啊啊') #自定制的write,不用在进行encode转成二进制去写了,简单,大气
f1.close()

#授权示范二

 

__format__用法

#自定义format练习

date_dic={
    'ymd':'{0.year}:{0.month}:{0.day}',
    'dmy':'{0.day}/{0.month}/{0.year}',
    'mdy':'{0.month}-{0.day}-{0.year}',
}
class Date:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day

    def __format__(self, format_spec):
        if not format_spec or format_spec not in date_dic:
            format_spec='ymd'
        fmt=date_dic[format_spec]
        return fmt.format(self)

d1=Date(2016,12,29)
print(format(d1))
print(format(d1,"dmy"))
print(format(d1,"mdy"))

 __slots__方法

#少用

class Foo:
    __slots__ = ["name","age"]

f1 = Foo()
print(Foo.__dict__)
f1.name = "tom"
f1.age = 18

# f1.gender = "man"  #不能设置__slots__里没有的属性

print(f1.name)
print(f1.age)

# print(f1.__dict__)  #设置了__slots__,实例的对象没有__dict__的属性字典

 __del__方法    析构方法

class Foo:
    def __del__(self):
        print("我执行了")


f1 = Foo()
del f1     #对象被删除时会调用__del__方法
print("-------------->")

#程序运行完时也会调用__del__方法,因为程序运行完,Python解释器会回收对象。

 __call__方法

#  __module__ 表示当前操作的对象在那个模块
#  __class__   表示当前操作的对象的类是什么

class Foo:
    def __call__(self, *args, **kwargs):
        print("执行了---")

f1 = Foo()

f1()  # f1的类Foo 下的__call__方法. 如果上面没有定义__call__方法,调用f1()用报错

Foo() # Foo的类 XXX 下的__call__方法

 

一 isinstance(obj,cls)和issubclass(sub,super)

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

 class Foo(object):
     pass
  
 obj = Foo()
  
 isinstance(obj, Foo)

 issubclass(sub, super)检查sub类是否是 super 类的派生类

class Foo(object):
    pass
 
class Bar(Foo):
    pass
 
issubclass(Bar, Foo)

 

 

 

posted on 2016-12-20 09:38  LiaoBS  阅读(127)  评论(0编辑  收藏  举报

导航