Python系列6之面向对象

目录

  • 生成器和迭代器
  • 字符串格式化
  • 内置函数vars
  • 反射
  • 面向对象编程

一. 生成器和迭代器

   1. 生成器

    生成器具有一种生成的能力,它仅仅代表着一种生成的能力,当我们需要使用的时候,才会通过迭代器去生成它。因为他只代表这一种生成的能力,因此,生成器比较节省内存,它一般通过yield来区分生成的位置。通过next来找到下一个位置。

# 当直接去执行genetor函数的时候,会先返回一个1,然后就退出了,因为遇到了yield
# 当用一个next之后就会执行2. 然后继续退出
# 也就是说yield其实是生成器的一个地址保存机制,只有通过next才会使他的地址指向下一个yield

def genetor():
    print(1)
    yield 1

    print(2)
    yield 2

    print(3)
    yield 3

    print(4)
    yield 4
obj=genetor()
a = obj.__next__()
b = obj.__next__()
c = obj.__next__()
d = obj.__next__()

  书写一个xrange函数

def xrange(args):
    value = 0
    while True:
        if value >= args:
            return
        else:
            yield  value
            value += 1
for i in xrange(5):
    print(i)

  2. 迭代器  

    迭代器代表这个一种访问的能力,他能够通过一次次的next去迭代生成器产生的对象,因此,他能够得到我们想要得到的数据。for循环就是一种迭代器。如上面的代码,我们可以通过for循环去迭代生成器。

二. 字符串格式化

  1. 字符串的格式化

    字符串的格式化比拼接的方式更加有效

    字符串的格式化更加的方便

  2. %格式化

# %的使用格式,[]里面的内容都可以省略

%[(name)][flags][width].[precision]typecode[(name)]
 格式:%[(name)][flags][width].[precision]typecode

 (name):        可选的,用于选择指定的key
 flags:          输入的格式是左对齐还是右对齐,和width一块使用,
    +           右对齐, 正数前面加+号, 负数前面加-号
    -           不变,就是左对齐
    空格         不变,就是右对齐
    0           右对齐,前面填充0
 width          可选,占有的宽度
 .precision     小数点后保留的位数
 typecode
    s           字符串
    f           有精度的数
    d           整数

  事例:

字符串

s1 = "I am %+10d, age %-10d, % 10d %010d" % (10, 10, 10, 10)
s2 = "I am %+10d, age %-10d, % 10d %010d" % (-10, -10, -10, -10)
print(s1)
print(s2)

结果:
I am        +10, age 10        ,         10 0000000010
I am        -10, age -10       ,        -10 -000000010

整数

# 常用事例:

s1 = "I am %s" % "hu"
s2 = "I am %(name)s, age%(age)s" % {"name": "hu", "age": 13}
s3 = "3.335 + 4.2345 = %2.f" % 7.23566
print(s1, s2, s3)

  3. format格式化的常用方法

  [[fill]align][sign][#][0][width][,][.precision][type] 这个是format的格式,很多和%都是一样的,下面只列举一下关于它的常见用法

s1 = "i am {}, {}, {}".format("hu", "zhou", "12")

s1 = "I am {}, {}, {}".format(*["hu", "zhou", "12"])

s1 = "I am {0}, {1}, {0}".format("seven", 18)

s1 = "I am {0}, {1}, {0}".format(*["seven", 19])

s1 = "I am {name}, {age}, {name}".format(name="hu", age=11)

s1 = "I am {name}, {age}, {name}".format(**{"name":"hu", "age":11})

s1 = "I am {:s}, {:d}, {:f}".format("hu", 18, 1823.923)

s1 = "{:b},{:x},{:o}".format(10,10,10)

s1 = "{:#b},{:#x},{:#o}".format(10,10,10)

三. 内置函数vars

#  内置函数的一些默认的变量

print(vars())
{‘__file__‘: ‘C:/Users/zhou/PycharmProjects/fullstack2/6_20/test.py‘, ‘__doc__‘: None, ‘__cached__‘: None, ‘__builtins__‘: <module ‘builtins‘ (built-in)>, ‘__spec__‘: None, ‘__package__‘: None, ‘__name__‘: ‘__main__‘, ‘__loader__‘: <_frozen_importlib_external.SourceFileLoader object at 0x00000063B24C4F98>}

  1.  __file__      当前工作的环境的绝对路径

  2. __name__    如果是在当前工作目录,则返回的是__main__, 如果是导入的模块,返回的就是模块的名字

  3. __packge__

  4. __doc__      这个变量保存的是这个文件的说明,也就是在文件开头部分对这个文件功能的说明

  5. __cached__  这个是缓存,如果是导入的模块就会有缓存

  6. __builtins__  这个是内置函数

‘‘‘
这个是一个测试文档
文档名称为test
‘‘‘
import index
print(index.__name__)
print(__name__)
print(__file__)
print(__doc__)
print(index.__cached__)

显示结果:
index
__main__
C:/Users/zhou/PycharmProjects/fullstack2/6_20/test.py

这个是一个测试文档
文档名称为test

C:\Users\zhou\PycharmProjects\fullstack2\6_20\__pycache__\index.cpython-35.pyc

四. 反射

  1. 反射的定义

    反射就是通过字符串的形式去某个对象中操作它的成员。

  2.  __import__方法和import的区别

    <1>. __import__可以通过字符串导入模块

    <2>. import 不能通过字符串来导入模块

      简单的import和__import__

# 此处s3是一个函数的名字
# 对于字符串,直接import导入会报错,
# 需要用__import__去导入,就相当于是import s3 

# import "s3"
module = __import__("s3")
module.f3()

      扩展的__import__, 当我们需要导入层级的模块的时候,需要用到fromlist参数

# lib目录下有个模块order,要导入的话就需要以下方法

module = __import__("lib.order", fromlist=True)
print(module.add_order())

  3. 反射的方法

    <1>. hasattr(模块, 关键字)     判断关键字是否在模块中,在的话返回true,不在的话返回false

    <2>. getattr(模块, 关键字)     如果关键字是一个函数,则返回函数,如果是一个变量,就返回变量(里面的关键字传递的都是字符串,如果是函数,字符串默认是使用不了的,通过这个函数可以转换成使用的函数)

    <3>. setattr(模块, 关键字, 值)     往模块中加入关键字,加入的可以是变量, 可以是函数,加入和删除都是在内存中完成的,并不会影响文件的内容

    <4>. delattr(模块,关键字)     从模块中删除关键字

s3的内容
def f1():
    print("f1")

=============================
# 导入s3,判断关键字是否在s3中
import s3
ret1 = hasattr(s3, "f1")
ret2 = hasattr(s3, "f11")
print(ret1)
print(ret2)

结果:
True
False

hasattr()

# 导入模块,通过字符串得到模块内函数
# 然后执行函数
# 字符串f1 是执行不了的,只能通过getattr得到函数在执行

import s3
func = getattr(s3, ‘f1‘)
func()

getattr()

# setattr传递的是一个键值对,而hasattr判断的只是键,而不是值,
# 因为刚开始还没有这个“name”,所以返回的是false,通过setattr设置了这个键,所以返回的是True

import s3
print(hasattr(s3, "name"))
setattr(s3, "name", "hu")
print(hasattr(s3, "name"))

结果:
False
True

setattr()

# 开始f1是存在的,所以返回True
# 通过del删除之后,在返回的就是False了

import s3
print(hasattr(s3, "f1"))
delattr(s3, "f1")
print(hasattr(s3, "f1"))

结果:
True
False

delattr()

url = input("请输入url:")
target_module, target_func = url.split("/")
print(target_func, target_module)
module = __import__("lib."+target_module, fromlist=True)
print(module)
if hasattr(module, target_func):
    # module.target_func()
    target_func = getattr(module, target_func)
    target_func()
else:
    print("404")

Python实例(基于web框架的路由系统)

五. 面向对象编程

  1. 编程

    其实在我们日常生活中,编程的方式有很多,例如:面向过程,面向对象,或者是函数式编程,他们的区别还蛮大的,但是最终的目的只有一个,那就是简化工作量。就像是盖房子,面向过程就是我要自己去买砖买瓦,自己垒砌,然后函数式编程就是我自己买砖买瓦,然后找木匠工人给我做,面向对象就是,我要直接买一套房子,省的自己做了。

  2. 面向对象编程

    (1). 定义类

      类是什么呢?类严格的定义是由某种特定的元数据所组成的内聚的包。他是由多个函数共同组成的为了完成某种功能的组合。既然有了函数,为什么还要类呢?当我们的函数出现大量的相同的参数或者相同的功能的时候,就需要类来简化其操作了

# 关键字class创建了一个类,类名为Foo
# 定义了三个方法,__init__ f1和f2
# 方法里面的self为默认的参数,必须带

class Foo:
    def __init__(self):
        self.Name = "hu"
    def f1(self):
        print("f1")
    def f2(self):
        print("f1")

    (2). 执行类(创建对象)

      对象是什么呢?在Python中,一切皆对象,当我们创建了一类数据之后,他只是一类数据,其中的方法,参数都都是泛华的东西,我们需要有一个对象来对其进行实例化。也就是说,当我们说:这有个人。你肯定不知道他是谁,因为他只代表了一类数据,当我们说:他是李刚,你就会恍然大悟,哦 ,他是李刚啊,这是因为我们吧类实例化了。

      __init__方法用来创建对象和封装内容

      每一个方法中的self变量都是Python中默认添加的,用来传递对象的。当我们创建了一个obj对象的时候,会自动的调用类中的__init__方法,然后把obj当做参数传递给self。

# 通过类名加括号去创建一个对象,并用对象去调用方法

class Foo:
    def __init__(self):
        self.Name = "hu"
    def f1(self):
        print("f1")
    def f2(self):
        print("f1")

obj = Foo()
obj.f1()

      创建对象的图示:都在内存中,创建一个对象的时候,默认的会去执行类中的__init__方法,通过init方法来产生右边的对象。

    

    (3). 三大特性

      在面向对象的语言中,一般都具有以下三种特性,封装,继承和多态。也正是因为这样,才构成了一个庞大的面向对象的系统,以至于你可以通过它来表述任何事物。千变万化。

       <1>. 封装

        封装就是把一系列相同的功能封装到对象中,从而简化类的方法。在介绍封装之前,我们先来比较一下封装和不封装的区别。

        由下面的例子我们就可以看出来,封装其实就是把一些重复的量统一的在一个地方进行定义,然后在利用。

#  没有封装数据
class Person:
    def chifan(self, name, age, gender):
        print(name, "吃饭")
    def shuijiao(self, name, age, gender):
        print(name, "睡觉")
    def dadoudou(self, name, age, gender):
        print(name,"打豆豆")

没有封装

class Person:
    def __init__(self, name, age, gender):
        self.Name = name
        self.Age = age
        self.Gender = gender
    def chifan(self):
        print(self.Name,"吃饭")
    def shujiao(self):
        print(self.Name,"睡觉")
    def dadoudou(self):
        print(self.Name,"打豆豆")

封装

        使用场景:

          a. 当同一类型的方法具有多个模板的时候,直接封装成对象即可
          b. 把类当做模板,创建多个对象(对象内封装的数不一样)

          例:定义了一个类Person,用__init__去封装了三个参数,以供下面的两个方法来调用,通过pickle模块来存档。

import pickle
class Person:
    def __init__(self, name, age, weight):
        self.Name = name
        self.Age = age
        self.Weight = weight
    def chi(self):
        self.Weight += 2
    def jianshen(self):
        self.Weight -= 1
ret = pickle.load(open(‘youxi‘, ‘rb‘))
if ret:
    print(ret.Weight)
    obj1 = Person(ret.Name, ret.Age, ret.Weight)
else:
    obj1 = Person(‘xiaoming‘, 12, 200)
    obj1.chi()
    obj1.chi()
    obj1.chi()
    obj1.jianshen()
pickle.dump(obj1, open(‘youxi‘, ‘wb‘))

       <2>. 继承

        我们都听说过子承父业,其实继承就是这个意思,当我们定义了几个类之后,发现这几个类都有一些共同的属性和方法,这个时候我们就可以把这几个共同的属性和方法定义成一个类来当做这几个类的父亲,然后这几个类就可以继承父亲的属性和方法来当做自己的方法。如下面这个例子,定义了三个类,一个父类,一个儿子,一个女儿,父类的方法有吃和喝,儿子的方法是票,女儿的方法是赌,当儿子继承了父亲,就会把父亲的方法继承下来,自然也就会了吃和喝,女儿也一样。

class Parent:
     def chi(self):
         print("吃")
     def he(self):
         print("喝")
class son(Parent):
    def piao(self):
        print("票")

class nver(Parent):
    def du(self):
        print("赌")

obj = son()
obj.chi()
obj.he()
obj.piao()
obj1 = nver()
obj1.chi()
obj1.he()
obj1.du()

        继承的规则

        1. 子类会默认的继承父类的所有方法

        2. 如果子类和父类有同样的方法,会优先的去用子类的方法

        3. Python中可以继承多个类(这个是Python的特点, C#和java都不具备)

        Python中继承多个类的顺序规则

        因为Python中可以多继承,因此当子继承父类的时候,它的规则一般是先执行左边的,后执行右边的,当有嵌套的时候,每次还要重新回到子类中去递归查找。如下面的例子

     例:当子类中的方法没有的时候就会依次的向上进行查找

# 创建了几个类,继承关系如上图中的一
class A:
    def f1(self):
        print("A")
class B:
    def f1(self):
        print("B")
class C(A):
    def f1(self):
        print("C")

class D(B):
    def f1(self):
        print("D")
class E(C, D):
    def f1(self):
        print("E")
obj = E()
obj.f1()

上图一

class Hu:
    def f1(self):
        print("Hu")
class A(Hu):
    def f1(self):
        print("A")
class B(Hu):
    def f1(self):
        print("B")
class C(A):
    def f1(self):
        print("C")

class D(B):
    def f1(self):
        print("D")
class E(C, D):
    def f1(self):
        print("E")
obj = E()
obj.f1()

上图二

       <3>. 多态

         因为在Python传参的时候本身就没有类型的约束,因此它本身就是多态的,我们可以把任意的数据传进去。

    (4). 成员

       方法: 静态方法(无需使用对象封装的内容@staticmethod,直接用类进行调用),普通方法(使用对象进行封装),类方法

       字段: 静态字段(每一个对象都会有一份),普通字段(使用对象中进行封装的)

       特性: 只有一种,将方法伪造成字段

       调用成员的方式:

         1. 如果没有self, 就用类进行调用

         2. 如果有self, 就用对象进行调用

   3. 异常处理

      在程序执行的过程中,会遇到一些未知的错误,但是我们总是希望把这些错误的以我们能控的方式返回给用户,这是就用到了异常处理。

      异常处理的格式:

# 当try后面的语句发生错误之后,就会触发后面的语句,返回一个我们可以控制的错误信息

a = input("输入一个数:")
try:
    a = int(a)
except Exception as e:
    print("出错了....")
时间: 2024-08-14 20:44:13

Python系列6之面向对象的相关文章

Python系列教程大汇总

Python初级教程 Python快速教程 (手册) Python基础01 Hello World! Python基础02 基本数据类型 Python基础03 序列 Python基础04 运算 Python基础05 缩进和选择 Python基础06 循环 Python基础07 函数 Python基础08 面向对象的基本概念 Python基础09 面向对象的进一步拓展 Python基础10 反过头来看看 Python补充01 序列的方法 Python中级教程 Python进阶01 词典 Pytho

【python】对象和面向对象

类的定义 python支持多重继承,在类名后面的小括号中,可以列出多个类名,以逗号分割. __init__方法在类的实例创建后被立即调用,注意与c++中构造函数不一样,因为对象在调用__init__时已经被构造出来,__init__方法不返回值,__init__方法不是必须要定义的. 每个类方法的第一个参数,包括__init__,都是指向类的当前实例的引用.按照习惯这个参数被称为self.在__init__方法中,self指向新创建的对象,在其他的类方法中,它指向方法被调用的类的实例.尽管当定义

python笔记 - day7-1 之面向对象编程

python笔记 - day7-1 之面向对象编程 什么时候用面向对象: 多个函数的参数相同: 当某一些函数具有相同参数时,可以使用面向对象的方式,将参数值一次性的封装到对象,以后去对象中取值即可: sele是什么? self是一个python自动会给传值得参数: 哪个对象执行方法,self就是哪个对象: 构造方法: 类中有一个特殊的方法,__init__,类()自动执行: 面向对象,三大特性: 封装,继承,多态:  

python学习笔记12-python面向对象

python学习笔记12-python面向对象 python一切皆对象 一.基本概念 1.面向对象和面向过程 面向对象编程:C++,Java,Python 面向过程编程:函数式编程,C程序等 2.类和对象 类:是对事物的抽象,比如:人类,球类 对象:是类的一个实例,比如:足球,篮球,对象就是对类的实例化 属性:五官,眼,鼻子,理解为一个变量,静态属性 方法:对人来说,吃穿住行,理解为一个函数,动态方法 实例说明:球类可以对球的特征和行为进行抽象,然后可以实例化一个真实的球实体出来 3.为什么要使

Python系列之 __new__ 与 __init__

很喜欢Python这门语言.在看过语法后学习了Django 这个 Web 开发框架.算是对 Python 有些熟悉了.不过对里面很多东西还是不知道,因为用的少.今天学习了两个魔术方法:__new__ 和 __init__. 开攻: 如果对 Python 有所简单了解的话应该知道它包含类这个概念的.语法如下: class ClassName: <statement - 1>: . . . <statement - N> 问题来了.像我们学习的 C# 或是 Java 这些语言中,声明类

【python系列】SyntaxError:Missing parentheses in call to &#39;print&#39;

打印python2和python3的区别 如上图所示,我的 PyCharm安装的是python3.6如果使用print 10会出现语法错误,这是python2.x和python3.x的区别所导致的. [python系列]SyntaxError:Missing parentheses in call to 'print'

初探接口测试框架--python系列7

点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是我们期待的方向,有更多兴趣的欢迎切磋,我们微信订阅号,联系方式如下: 更多书籍,敬请期待 背景说明 python系列课程也有段时间了,我们坚持,一步步来,今天是最后一课的分享,看看接口测试框架的神秘,小怪带领着大家一起完成第7课,希望能看完知识点,自己动手练习,然后和给出的例子代码对比,最后看看作业

总结整理 -- python系列

python系列 python--基础学习(一)开发环境搭建,体验HelloWorld python--基础学习(二)判断 .循环.定义函数.继承.调用 python--基础学习(三)字符串单引号.双引号.三引号 python--基础学习(四)自然字符串.重复字符串.子字符串 python--基础学习(五)参数位置传递.关键字传递.包裹传递及解包裹 python--基础学习(六)sqlite数据库基本操作 python--爬虫入门(七)urllib库初体验以及中文编码问题的探讨 python--

Python, Java, C++, Perl 面向对象思想比较

面对对象语言的设计哲学通常分为以下两种. 第一种思路是基类的作者定下一系列的规则,规定使用该基类的人(派生类的作者)可以干什么事,不能干什么事. C++,和 Java 就是这一阵营的主要代表.比如说,C++中类定义中的 public, protected, private, virtual 等关键字就是 所谓的规则,规定了类的用户可以使用的成员,必须继承接口,或者实现等等. 这些规则强制类的用户调用或使用基类作者所允许的成员. 这样的好处在于,当错误使用发生的时候,编译器会发出牢骚,进而阻止错误