python之面向对象

一.初识面向对象

  1.类与对象的关系: 类是对事物的总结. 抽象的概念. 类用来描述对象. 对象是类的实例化的结果. 对象能执行哪些方法. 都由类来决定. 类中定义了什么. 对象就拥有什么

    class 类名:

      方法
    类()        #对象

class Car:
    pass
Car()
  •  注意:类名的首字母大写,严格遵守驼峰命名规范    

    1.1python中我们可以是用__init__(self)函数给对象进行初始化操作. 这个函数(方法)被称为构造函数(方法)或初始化方法

  •     在创建对象的时候会自动的调用 __init__()
  •     self是你创建出来的那个对象
class Car: #创建类
    def __init__(self,color)
        self.color=color#属性
c = Car() #创建对象

    1.2 方法 ->在类中的函数

class Phone:  #创建类
    def __init__(self,color,price):  #初始化方法(构造方法)  自动调用
        self.color=color #属性
        self.price=price #属性
    def call(self,man):  #方法
        print(f'用我{self.color}手机给{man}打电话')
    def play(self):  #方法
        print('我%s的手机可以打游戏' % self.price)
p = Phone('红色',5000)
p.call('马云')
p.play()

  2.面向对象和面向过程的对比    

    2.1⾯向过程: 一切以事物的流程为核心. 核心是"过程"二字, 过程是指解决问题的步骤,即, 先干什么, 后干什么.

  •     优点: 负责的问题流程化, 编写相对简单
  •     缺点: 可扩展性差

    2.2面向对象: 一切以对象为中心.

  •     优点: 可扩展性强
  •     缺点: 编程的复杂度高于⾯面向过程

  3.面向对象的三个特征

  •   ⾯向对象三大特征: 封装, 继承, 多态. 只要是面向对象编程语言. 都有这三个特征.

    3.1. 封装: 把很多数据封装到一个对象中. 把固定功能的代码封装到一个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想.

    3.2. 继承: 子类可以自动拥有父类中除了私有属性外的其他所有内容. 在python中实现继承非常简单. 在声明类的时候, 在类名后面添加一个小括号,就可以完成继承关系. 那么什么情况可以使用继承呢?  两个类具有相同的功能或者特征的时候. 可以采用继承的形式. 提取一个父类, 这个父类中编写着两个类相同的部分. 然后两个类分别取继承这个类就可以了了.

  •   这样写的好处是我们可以避免写很多重复的功能和代码. 如果从语义中去分析的话. 会简单很多. 如果语境中出现了x是一种y. 这时, y是⼀一种泛化的概念. x比y更加具体. 那这时x就是y的子类.

    3.3. 多态: 同一个对象, 多种形态.

  •     多态的好处: 程序具有超⾼高的可扩展性. ⾯面向对象思想的核⼼心与灵魂.    

二.类的成员

    什么是类的成员? 你能在类中写什么? 写的内容就是成员.

class 类名:
    # 方法
    def __init__(self, 参数1, 参数2....):
    # 属性变量
        self.属性1 = 参数1
        self.属性2 = 参数2
        ....
    # 方法
    def method(self):
        pass            

  1.类的成员------变量

    1.1.实例变量,类变量(静态变量)

  •       实例变量是给对象用的,
  •      类变量对多个对象共享,最好用类名来访问
class Person:
    country = "中国"  # 类变量, 表示所有的该类的对象都共享这个变量.
    def __init__(self, name, num, birthday):
        # 实例变量(字段) 表示你创建的每⼀个人都有这三个变量量
        self.name = name
        self.num = num
        self.birthday = birthday
p1 = Person("alex", 18, "1840年年06⽉月01⽇日")
print(p1.name) 
print(p1.country) #中国
p2 = Person("wusir", 28, "1894年年07⽉月25⽇日")
print(p2.name) 
print(p2.country)   #中国
  

  2.类的成员------方法

    2.1.实例方法(成员方法)  对象直接访问的方法叫实例方法

class Computer:
    def play(self): #实例方法  参数为self
        print('电脑可以玩')
c = Computer()
c.play()   #对象直接调用实例方法

    2.2.类方法   @classmethod

    类方法需要在参数列表中的第一个位置预留一个位置, 通常我们给第一个参数起名字叫cls. 类方法在被调用的时候也不需要传递实例对象.但是. 系统会自动的把类传递给第一个参数. 类方法在编写的时候, 需要在类方法上面添加@classmethod

class Phone:
@classmethod
def play(cls): #类方法 参数必须是cls
print('我的手机可以打游戏')

    2.3.静态方法  @staticmethod

  •   静态方法不需要我们给方法传递self. 也就是说. 当出现一个方法不需要使用到成员变量的时候. 就可以选择使用静态方法. 静态方法需要我们在方法上面添加一个@staticmethod
  •   静态方法和静态变量一样. 一般都是使用类名直接访问和调⽤用的.
class Phone:
    @staticmethod
    def func():  #静态方法   没有参数
        print('我的电话可以打电话')

  3.类的成员------属性  

    属性其实就是通过方法改造过来的一种变量的写法, 在方法上添加⼀个@property就可以了

注意:
  1. ⽅法参数只能有⼀个self
  2. ⽅法上⽅要写@property
  3. 调用的时候, 我们不需要写括号. 直接当成属性变量来用就可以了.
  4. 这种套路只能取值. 不能设置值

class Person:
    def __init__(self):
        pass
    @property
    def age(self):
        return 1
p = Person()
age = p.age
print(age)        

  4.私有方法和私有变量

  在python中使用__作为⽅法或者变量的前缀. 那么这个方法或者变量就是一个私有的.

class Person:
    def __init__(self, mimi):# 私有变量
        self.__mimi = mimi    
     def __age(self):#私有方法
        print("不告诉你")`

三.类与类之间的关系

  1.依赖关系

 

class Elphant:
    def __init__(self, name):
        self.name = name
    def open(self):
        '''
        开门
        :return:
        '''
        pass
    def close(self):

        '''
        关门
        :return:
        '''
        pass
class Refrigerator:
    def open_door(self):
        print("冰箱门被打开了")
def close_door(self):
    print("冰箱门被关上了")
#大象和冰箱之间就是依赖关系. 我用着你. 但是你不属于我. 这种关系是最弱的.

 

  

 

  2.关联关系,组合关系,聚合关系

       其实这三个在代码上写法是一样的. 但是, 从含义上是不一样的.

  •     关联关系. 两种事物必须是互相关联的. 但是在某些特殊情况下是可以更改和更换的.

  •     聚合关系. 属于关联关系中的一种特例. 侧重点是xxx和xxx聚合成xxx. 各自有各自的声明周期. 比如电脑. 电脑⾥里里有CPU, 硬盘, 内存等等. 电脑挂了了. CPU还是好的. 还是完整的个体

  •     组合关系. 属于关联关系中的一种特例例. 写法上差不多. 组合关系比聚合还要紧密. 比如人的大脑, 心脏, 各个器官. 这些器官组合成一个人. 这时. 人如果挂了. 其他的东西也跟着挂了

  3.继承关系

    在面向对象的世界中存在着继承关系. 我们现实中也存在着这样的关系. 比如. x是一种y, 那x就可以继承y. 这是理解层面上的. 如果上升到代码层面. 我们可以这样认为. 子类在不影响父类的程序运行的基础上对父类进行的扩充和扩展. 这里.我们可以把父类被称为超类或者基类. 子类被称为派生类

 

class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
class Foo(Base):
    def func1(self):
        print("Foo. func1", self.num)
obj = Foo(123)
obj.func1()     # Foo. func1 123 运行的是Foo中的func1

 

  

 

四.特殊成员

  1. 类名() 会自动执行__init__()
  2. 对象() 会自动执行__call__()
  3. 对象[key] 会自动执行__getitem__()
  4. 对象[key] = value 会自动执行__setitem__()
  5. del 对象[key] 会自动执行 __delitem__()
  6. 对象+对象 会自动执行 __add__()
  7. with 对象 as 变量 会自动执行__enter__ 和__exit__
  8. 打印对象的时候 会自动执行 __str__
  9. 干掉可哈希 __hash__ == None 对象就不可哈希了.

  • 创建对象的真正步骤:

    首先, 在执行类名()的时候. 系统会自动先执行__new__()来开辟内存. 此时新开辟出来的内存区域是空的. 紧随其后, 系统自动调用__init__()来完成对象的初始化工作. 按照时间轴来算.

    1. 加载类
    2. 开辟内存(__new__)
    3. 初始化(__init__)
      4. 使用对象干xxxxxxxxx

五.反射

  1.isinstance  type和issubclass的应用

  •   issubclass() 这个内置函数可以帮我们判断xxx类是否是yyy类型的子类.
class Base:
    pass
class Foo(Base):
    pass
class Bar(Foo):
    pass
print(issubclass(Bar, Foo)) # True
print(issubclass(Foo, Bar)) # False
print(issubclass(Bar, Base)) # True
  •  type(obj) 表示查看obj是由哪个类创建的.

class Foo:
    pass
obj = Foo()
print(obj, type(obj)) # 查看obj的类
  •   isinstance也可以判断xxx是yyy类型的数据.但是isinstance没有type那么精准.

  •        isinstance可以判断该对象是否是xxx家族体系中的(只能往上判断)

class Base:
    pass
class Foo(Base):
    pass
class Bar(Foo):
    pass
print(isinstance(Foo(), Foo)) # True
print(isinstance(Foo(), Base)) # True
print(isinstance(Foo(), Bar)) # False

  2.函数和方法的区分

  •   函数在打印的时候. 显示的是function. 而方法在打印的时候是method.
class Foo:
    def chi(self):
        print("我是吃")
    @staticmethod
    def static_method():
        pass
    @classmethod
    def class_method(cls):
        pass
f = Foo()
print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 0x10f688550>>
print(Foo.chi) # <function Foo.chi at 0x10e24a488>
print(Foo.static_method) # <function Foo.static_method at 0x10b5fe620>
print(Foo.class_method) # bound method Foo.class_method of <class '__main__.Foo'>>
print(f.static_method) # <function Foo.static_method at 0x10e1c0620>
print(f.class_method) #<bound method Foo.class_method of <class '__main__.Foo'>>

  仔细观察, 我们能得到以下结论:

  •   1. 类方法. 不论任何情况, 都是方法.
  •   2. 静态方法, 不论任何情况. 都是函数
  •   3. 实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数.

  3.反射

  关于反射, 其实一共有4个函数:

  •   1. hasattr(obj, str) 判断obj中是否包含str成员
  •   2. getattr(obj,str) 从obj中获取str成员
  •   3. setattr(obj, str, value) 把obj中的str成员设置成value. 注意. 这里的value可以是值, 也可以是函数或者方法
  •   4. delattr(obj, str) 把obj中的str成员删除掉

六.约束,异常抛出,异常处理,MD5和日志的处理

1.约束

2.异常抛出

3.日常处理

4.MD5加密算法

 

5.日志

import logging

# 配置好日志的处理, 默认就是GBK
logging.basicConfig(filename='x1.txt', # 把日志信息写入的文件名
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S', # 时间的格式
                    level=10) # 当前配置表示 10以上的分数会被写入日件

# 向日志文件写入内容
logging.critical("最高的") # 50, 几乎是最高的
logging.error("最多的") # 40 平时使用最多的就是它
logging.warn("警告") # 30  警告
logging.warning("警告")
logging.info("提示") # 20 级
logging.debug("最低的") # 10
logging.log(999, "自己定义一个等级")  #自己定义一个等级

 

# 再创建⼀个操作⽇志的对象logger(依赖FileHandler)
file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')
file_handler2.setFormatter(logging.Formatter(
    fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
logger2 = logging.Logger('百度贴吧', level=logging.DEBUG)
logger2.addHandler(file_handler2)
logger2.error("我才不去呢. 我们在北京. 离你那么远")
import traceback
class GenderException(Exception):
    pass
class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        logger1.info(f"这个人的名字是{self.name}, 这个人的性别是:{self.gender}")

    def xizao(self):
        print(f"{self.name}在洗澡")

class ZaoTang:

    def nan(self, ren):
        if ren.gender == "男":
            ren.xizao()
        else:
            raise GenderException("我这里要的是男人")

    def nv(self, ren):
        if ren.gender == "女":
            ren.xizao()
        else:
            raise GenderException("我这里要的是女人")


try:
    p1 = Person("赵亚磊", "男")
    p2 = Person("林志玲", "女")
    zaotang = ZaoTang()
    zaotang.nan(p2)
    zaotang.nv(p1)
except GenderException:
    print("走错屋里了")
    logger1.error("走错屋了.. ")
    logger1.error(traceback.format_exc()) # 把堆栈信息记录在日志文件中

七.MRO C3算法

  

 

  

  

 

posted @ 2018-12-24 16:59  QV  阅读(252)  评论(0编辑  收藏  举报