初识面向对象

1.   面向过程:  一切以事物的流程为核心.  核心是"过程"二字, 过程是指解决问题的步骤, 即, 先干什么, 后⼲什么. 基于该思想编写程序就好比在编写一套流水线. 是一种机械式的编程思维

优点:  负责的问题流程化, 编写相对简单

缺点:  可扩展性差

2. 面向对象: 一切以对象为中⼼.

什么是对象?  不好解释. 先解释解释么是车?  有轱辘, 有方向盘, 有发动机, 会跑的 是车. 好. 在解释一个. 什么是人. 有名字, 年龄, 爱好, 会唱歌跳舞思考的是人. 我们给这两个 东西下了一个简单的定义.  总结: 具有相同属性和动作的结合体叫对象. 面向对象思维, 要⾃己建立对象. ⾃己建立场景. 你是就是面向对象世界中的上帝. 你想让车干嘛就干嘛. 你想让人干嘛人就能干嘛.

优点:  可扩展性强

缺点:  编程的复杂度高于面向过程

创建类:

class 类名:(类名首字母一般大写)

创建对象:
变量(引用, 句柄) = 类名(参数)

# 访问对象的属性信息
对象.属性
# 方法的访问:
对象.方法()

总结:

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

3.⾯向对象三大特征:

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

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

2. 继承:  子类可以自动拥有父类中除了私有属性外的其他所有内容.  说白了, 儿子可以 随便便用爹的东西. 但是朋友们, 一定要认清楚一个事情. 必须先有爹, 后有儿子.  顺序不能乱,  python中实现继承非常简单. 在声明类的时候, 在类名后面添加一个小括号, 就可以完成继承关系.两个类具有相同的功能或者特征的时候. 可以采用继承的形式. 提取⼀一个父类, 这个父类 中编写着两个类相同的部分. 然后两个类分别取继承这个类就可以了了. 这样写的好处 是我们可以避免写很多重复的功能和代码.

3. 多态: 同一个对象, 多种形态. 这个在python中其实是很不容易说明⽩的. 因为我们⼀ 直在用. 只是没有具体的说.  比如. 我们创建一个变量a = 10 , 我们知道此时a是整数 类型. 但是我们可以通过程序让a = "ex", 这时, a又变成了字符串类型.  这是我们都知道的. 但是, 我要告诉你的是. 这个就是多态性. 同一个变量a可以是多种形态. 可能这样的程序和说法你还get不到具体什么是多态.

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

一.类的成员

class 类名:

  # 方法

  def __init__(self, 参数1, 参数2....):

    # 属性变量

    self.属性1 = 参数1

    self.属性2 = 参数2        ....

  # 方法

  def method(self):

    pass

在上面代码中__init__和method都属于类的成员方法.  又称为实例⽅法.  总之这样的东⻄ 需要用对象来访问.  而上方的self.属性1 = 参数1 这个代码的含义是给对象设置属性信息. 含义是这个对象的xxx属性是xxxx. 这种东西又被称之为成员变量或者实例变量, 再或者被称之为字段. 都是一个意思.

二. 类的成员-变量

在类中变量分成两⼤类: 1. 实例变量(字段) 2. 类变量(静态变量)

来做个简单的总结:

实例变量,  给对象用的.

类变量,  多个对象共享的. 最好是用类名来访问. 这样更加规范.

二. 类的成员-方法

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

2. 静态方法

静态方法不需要我们给方法传递self.  也就是说. 当出现一个方法不需要使用到成员变量的时候. 就可以选择使用静态方法.  静态方法需要我们在方法上面添加一 个@staticmethod

3. 类方法

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

面试题: 类方法/静态方法和实例方法有什么区别?

类的成员-属性

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

应用场景: 我们一般保存数据的时候, 不会保存一个人的年龄. 因为随着时间的推移. 每个人的年龄都时刻在改变着. 那如何保存加完美呢? 很简单. 保存出⽣年⽉⽇. 然后用程序来 计算,你当前的年龄. 实时的. 那这个时候就需要相应的计算了. ⽽计算属于一个功能. 当然要写方法里了. 但是对于年龄这个属性⽽言. 他应该是一个数值. ⽽不是动作. 所以python 就提供了这样一种机制. 通过方法来描述一个属性.

注意:

1. 方法参数只能有一个self

2. 方法上要写@property

3. 调用的时候, 我们不需要写括号. 直接当成属性变量来用就可以了.

4. 这种套路只能取值. 不能设置值

四. 私有

在python中, 一般是不提倡设置和使用私有信息的. 但有些场景, 我们不得不这么做

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

私有的内容不能直接访问. 但是如果对方开辟了外界访问的通道(公共方法). 那可以 通过这个公共的⽅法来获取到私有的内容.

类变量(静态变量)一样拥有这样的属性:

2. 私有方法

私有方法, 顾名思义, 只能⾃己访问的方法. 别人都不能随便调用的

需要注意的是, 对于私有的内容⽽言. 子类是无法继承的.

类与类之间的关系:

1. 依赖关系

在方法中给方法传递一个对象. 此时类与类之间的关系是最轻的

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

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

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

2. 聚合关系. 属于关联关系中的一种特例. 侧重点是xxx和xxx聚合成xxx

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

继承关系

子类在不 影响父类的程序运行的基础上对父类进行的扩充和扩展. 这里.我们可以把父类被称为超类或者基类. 子类被称为派生类.

self在访问方法的顺序:  永远先找⾃己的. ⾃己的找不到再找父类的.

self就是你访问方法的那个对象.  先找⾃己, 然后在找父类

类的特殊成员:.

__init_()就是一个特殊的成员. 说白了. 带双下划线的那一坨.  这些方 法在特殊的场景的时候会被自动的执行,如:

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

一.   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是由哪个类创建的.

可以帮我们判断xxx是否是xxx数据类型的

type 获取到xxx对象的类型

isinstance也可以判断xxx是yyy类型的数据. 但是isinstance没有type那么精准.

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

如何判断一个方法或者一个函数(FunctionType, MethodType)

from types import FunctionType, MethodType

  print(isinstance(xx, FunctionType)))

  print(isinstance(xx, MethodType)))

二、区分方法和函数

1. 类方法. 不论任何情况, 都是方法.

2. 静态方法, 不论任何情况. 都是函数

3. 实例方法, 如果是实例(对象)访问. 就是方法. 如果是类名访问就是函数.

三、反射

两个函数. 一个是getattr(). 一个是hasattr().  其中getattr()用来获 取信息. hasattr()用来判断xxx中是否包含了了xxx功能,

那么我们可以在模块中这样来使用反射. 在面向对象中一样可以这样进行操作.

getattr(对象, 字符串):  从对象中获取到xxx功能. 此时xxx是一个字符串. get表示找, attr 表⽰属性(功能).

补充:

关于反射, 其实一共有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成员删除掉

注意, 以上操作都是在内存中进行的. 并不会影响你的源代码

约束

1. 约束(1. 抛出异常, 2. 写抽象类)
1. 抛出异常; NotImplementedError

 class Base:
def login(self):
raise Exception("你没有实现login⽅方法()")
class Normal(Base):
def login(self):
pass
class Member(Base):
def denglu(self):
pass
class Admin(Base):
def login(self):
pass
# 项目经理理写的总入口
def login(obj):
print("准备验证码.......")
obj.login()
print("进⼊入主⻚页.......")
n = Normal()
m = Member()
a = Admin()
login(n)
login(m) # 报错.
login(a)

2. 抽象类
from abc import ABCMeta, abstractmethod

  class Base(metaclass = ABCMeta): 抽象类

    @abstractmethod
    def 方法(self):pass

  class Foo(Base): 子类必须重写父类中的抽象方法
    def 方法(self):
      pass

 from abc import ABCMeta, abstractmethod
class Base(metaclass=ABCMeta):
@abstractmethod
def login(self):
pass
class Normal(Base):
def login(self):
pass
class Member(Base):
def denglu(self): # 这个就没用了
pass
def login(self): # ⼦类对父类进行实现
pass
class Admin(Base):
def login(self):
pass
# 项⽬目经理理写的总⼊入⼝口
def login(obj):
print("准备验证码.......")
obj.login()
print("进⼊入主⻚页.......")
n = Normal()
m = Member()
a = Admin()
login(n)
login(m)
login(a)

一个类包含类抽象方法. 这个类一定是抽象类
抽象类中可以有正常的方法

抽象类中如果有抽象方法. 这个类将不能创建对象

接口: 类中都是抽象方法

2. 异常处理
try:

except Error as e:

except....

else:

finally:
收尾

import traceback
try:
# 尝试执行的代码
except Exception as e:
# 除了错之后要做什么

要引入一个模块traceback. 这个模块可以获取到我们每个方法的调用信息. 又被成为堆栈信息
traceback.format_exc() # 获取堆栈信息(错误信息)

3.md5加密

MD5是一种不可逆的加密算法

 import hashlib
def my_md5(s):
obj = hashlib.md5(b"fjlksajflkjasfsalwer123dfskjf")
obj.update(s.encode("utf-8")) # 加密的必须是字节
miwen = obj.hexdigest()
return miwen

4. 日志处理
logging

critical
error(最多)
wraning
info
debug.

1. 导入logging模块.

2. 简单配置⼀一下logging

3. 出现异常的时候(except). 向日志里写错误信息.

# filename: 文件名

# format: 数据的格式化输出. 最终在日志文件中的样⼦子

#   时间-名称-级别-模块: 错误信息

# datefmt: 时间的格式

# level: 错误的级别权重, 当错误的级别权重大于等于leval的时候才会写⼊文件

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以上的分数会被写⼊入⽂文件

# CRITICAL = 50

# FATAL = CRITICAL

# ERROR = 40

# WARNING = 30

# WARN = WARNING

# INFO = 20

# DEBUG = 10

# NOTSET = 0

logging.critical("我是critical") # 50分. 最贵的

logging.error("我是error") # 40分
logging.warning("我是警告") # 警告 30

logging.info("我是基本信息") # 20

logging.debug("我是调试") # 10

logging.log(2, "我是⾃自定义") # 自定义. 看着给分

日志的分开记录

import logging 
# 创建一个操作日志的对象logger(依赖FileHandler)
file_handler = logging.FileHandler('l1.log', 'a', encoding='utf-8')
file_handler.setFormatter(logging.Formatter(fmt="%(asctime)s - %(name)s - % (levelname)s -%(module)s: %(message)s"))
logger1 = logging.Logger('s1', level=logging.ERROR)
logger1.addHandler(file_handler)
logger1.error('我是A系统')
# 再创建一个操作日志的对象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('s2', level=logging.ERROR)
logger2.addHandler(file_handler2)
logger2.error('我是B系统')

1. 多继承
继承: x是一种y的时候.可以使用继承关系. 即"is a"关系
一个类同时继承多个类(python, c++)

2. 经典类的MRO
通过数型结构的深度优先遍历
一条道走到黑(从左往右)

3. 新式类的MRO(重点, 难点) C3算法
先拆分再合并 第一项的头和后面所有项的尾进行比较 如果出现了. 就拿出来 如果没出现. 下一项....

新式类通过__mro__可以直接看到MRO的结果

 class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
class E(C, A):
pass
class F(D, E):
pass
class M(F, E):
pass
class N:
pass
class P(M,N):
pass
class G(P):
pass
class O:
pass
class X(O):
pass
class H(G, X, F):
pass
print(H.__mro__)
'''
L(H) = H + L(G) + L(X) + L(F) + GXF HGPMXFDBECANO L(G) = G + L(P) + P # GPMFDBECAN
L(X) = X + L(O) + O # XO
L(F) = F + L(D) + L(E) + DE # FDBECA L(P) = P + L(M) + L(N) + MN # PMFDBECAN
L(D) = D + L(B) + L(C) + BC # DBCA
L(E) = E + L(C) + L(A) + CA # ECA L(M) = M + L(F) + L(E) + FE # ECA ECA E MFDBECA '''

4.super()

super() 找MRO顺序的下一个

super()可以帮我们执行MRO中下一个父类的方法. 通常super()有两个使用的地方:

1. 可以访问父类的构造⽅方法

2. 当子类⽅法想调用父类(MRO)中的方法

结论: 不管super()写在哪儿. 在哪儿执行. 一定先找到MRO列表. 根据 MRO列表的顺序往下找. 否则一切都是错的!

day16 类的更多相关文章

  1. day16 类之间的关系 特殊成员

    类与类之间的关系1.依赖关系(一个对象当另一个对象的参数)  关系最浅, 特殊成员: 1. 类名() 会自动调用 __init__() class Foo: def__init__(self, nam ...

  2. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  3. 老男孩python第六期

    01 python s6 day7 上节回顾02 python s6 day7 SNMP使用03 python s6 day7 大型监控架构讲解04 python s6 day7 Redis使用05 ...

  4. [Day16]常用API(正则表达式、Date类、DateFormat类、Calendar类)

    1.正则表达式(Regular Expression,regex)-是一个字符串,使用单个字符串来描述.用来定义匹配规则,匹配一系列符合某个句法规则的字符串 1.1匹配规则: (1)字符:x -代表的 ...

  5. day16 常用类(String、StringBuffer、StringBuilder)

    1.String是唯一一个可以直接用常量赋值的引用数据类型. String的常量也是一个对象. 数据段——字符串常量池. 2.每一个字符串常量对象在加载期放入字符串常量池. java对String常量 ...

  6. python_way day16 DOM

    Python_way day16 1.Dom  (找到html中的标签) 一.DOM 1.查找元素 直接查找 document.getElementById 根据ID获取一个标签 --->这里是 ...

  7. 与文件上传到的三个类:FileItem类、ServletFileUpload 类、DiskFileItemFactory类

    文件上传: ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中, 在使用ServletFileUpload对象解析请求时需要根据DiskFi ...

  8. 反射 类的加载 Schema DOM 解析方式和解析器 命名空间

    Day15 反射 1.1 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. l 加载 就是指将class文件读入内存,并为之创建 ...

  9. java_23 File类

    1.File类定义: 文件和目录路径的抽象表达形式,java中将路径或者文件封装成File对象. 2.File类的静态成员变量(pathSeparator 分隔符,字符串        separat ...

随机推荐

  1. Hive学习之路 (十九)Hive的数据倾斜

    1.什么是数据倾斜? 由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点 2.Hadoop 框架的特性 A.不怕数据大,怕数据倾斜 B.Jobs 数比较多的作业运行效率相对比较低,如子查询比较 ...

  2. virtualbox+vagrant学习-2(command cli)-3-vagrant destroy命令

    Destroy 格式: vagrant destroy [options] [name|id] 此命令会停止vagrant管理的正在运行的机器,并销毁在机器创建过程中创建的所有资源.在运行这个命令之后 ...

  3. 文件上传之MultipartFile使用

    转载 文件断点上传,html5实现前端,java实现服务器 一.单/多文件上传使用例子: 工程路径如下 -src |--main.java    --controller    --service  ...

  4. 【转】python中的对象拷贝

    转自:https://www.cnblogs.com/bhlsheji/p/5352330.html python中.进行函数參数传递或者返回值时,假设是一般的变量,会拷贝传递.假设是列表或字典则是引 ...

  5. Python的编码注释【转】

    格式有多种,但必须有coding:[编码]或者coding=[编码],如: # -*- coding:utf-8 -*- #  coding:utf-8 # coding=utf-8 转自:https ...

  6. 【转载】Caffe + Ubuntu 14.04 + CUDA 6.5 新手安装配置指南

    洋洋洒洒一大篇,就没截图了,这几天一直在折腾这个东西,实在没办法,不想用Linux但是,为了Caffe,只能如此了,安装这些东西,遇到很多问题,每个问题都要折磨很久,大概第一次就是这样的.想想,之后应 ...

  7. C库函数重定向问题

    C库函数重定向用户能定义自己的C语言库函数,连接器在连接时自动使用这些新的功能函数.这个过程叫做重定向C语言库函数,如下图所示.举例来说,用户有一个I/O设备(如UART).本来库函数fputc()是 ...

  8. The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does not exist.

    The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does no ...

  9. oracle 导入报错:field in data file exceeds maximum length

    今天用sqlldr导入数据时候报错: " Record 1: Rejected - Error on table ks_test, column khname.Field in data f ...

  10. linux 系统运行级别一般为 0-6,请分别写出每个级别的含义

    每个运行级别的含义 0   关机模式(不要把启动级别  运行级别设置为0) 1   单用户模式 2   无NFS多用户模式 3   文本模式(命令行模式,完整的多用户模式) 4   未使用的 5   ...