第7天主要是面向对象的内容。

学到现在越来越吃力了,从上节课开始博客就没时间写了,看看别人写的博客都那么棒。又想起了那句话比你牛逼的人都在努力,你却在放羊。。。唉,我写作业的效率有点低,以后得抓紧时间了。

摘要:

1. 面向对象的编程方法

2. 面向对象的三大特性

3. Python类相关知识

4. 反射(经常用到)

1. 面向对象的编程方法

1.1 什么是面向对象的编程方法?

面向对象编程(Object-Oriented Programming ):将所需要设计的对象抽象成各类具体的属性,它的集合就是类。开发正规的程序跟写一个运行一次就扔了的小脚本一个很大不同就是,你的代码总是需要不断的更改,不是修改bug就是添加新功能等,所以为了日后方便程序的修改及扩展,你写的代码一定要遵循易读、易改的原则(专业数据叫可读性好、易扩展)。其实OOP编程的主要作用也是使你的代码修改和扩展变的更容易。

1.2 为什么要面向对象编程?

是为了更好地处理:1)避免写重复代码,2)灵活的修改代码

1.3 面向对象编程与函数式编程的区别?

面向对象编程=>创建对象,通过对象执行方法

函数式编程=>执行函数

2. 面向对象的三大特性

面向对象的三大特性:封装、继承、多态

2.1 封装

封装可以分为两部分来理解:1)封装,2)调用封装

# 创建一个Person类
class Person(object):
    # 类的构造方法,实例化时自动执行
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 实例化一个Person类的对象,自动执行类中的__init__方法
# 将alex和18封装到person1的name和age属性中
person1 = Person("alex", 18)

# 实例化一个Person类的对象,自动执行类中的__init__方法
# 将qimi和20封装到person2的name和age属性中
person2 = Person("qimi", 20)

# 调用alex的封装
print(person1.name)    # 输出=> alex

# 调用20的封装
print(person2.age)    # 输出=> 20

2.2 继承

对于面向对象来说,继承其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

# 创建一个Person类
class Person(object):
    # 父类的构造方法,实例化时自动执行
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 父类的方法
    def print(self):
        print("{} is {} years old.".format(self.name, self.age))

# 定义一个Teacher的类,继承Person类
class Teacher(Person):

    # 不推荐这么写
    # def __init__(self, habit):
    #     super(Person, self).__init__()
    #     self.habit = habit

    # 旧的写法,也不推荐这么写
    # def __init__(self, name, age, habit):
    #     Person.__init__(self, name, age)
    #     self.habit = habit

    # 推荐写法,在子类的构造方法里只出现子类的类名
    def __init__(self, name, age, habit):
        super(Teacher, self).__init__(name, age)
        self.habit = habit

   # 或者可以写得更简单一些,跟上面的写法是等价的。    def __init__(self, name, age, habit):
        super().__init__(name, age)
        self.habit = habit
  

    # 定义一个方法
    def get_habit(self):
        print("The habit of {} is {}.".format(self.name, self.habit))

# 实例化一个老师
alex = Teacher("alex", 18, "Girl")
# 调用父类的方法
alex.print()
# 调用本类的方法
alex.get_habit()

==============================================
output==>
alex is 18 years old.
The habit of alex is Girl.

多继承:

class D(object):
    def bar(self):
        print 'D.bar'

class C(D):
    def bar(self):
        print 'C.bar'

class B(D):
    def bar(self):
        print 'B.bar'

class A(B, C):
    def bar(self):
        print 'A.bar'

a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()

当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

经典类(深度优先):首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中没有,则继续去C类中找,如果还是未找到,则报错。

新式类(广度优先):首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中没有,则继续去D类中找,如果还是未找到,则报错。

注意:①在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了。

   ②Python3里为广度优先。

2.3 多态

多态性(polymorphisn)是允许你将父类对象设置成和一个或更多的他的子类对象相等的技术,赋值之后,父类对象就可以根据当前赋值给它的子类对象的特性以不同的方式运作。简单来说就是:允许将子类类型的指针赋值给父类类型的指针。
那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了实现--代码重用。而多态则是为了实现另一个目的--接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
Pyhon不支持多态并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
# 定义父类Animal
class Animal:
    def __init__(self, name):    # Constructor of the class
        self.name = name

    # 定义一个供子类复写的方法
    def talk(self):              # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")

# 定义子类Cat
class Cat(Animal):
    def talk(self):
        return 'Meow!'

# 定义子类Dog
class Dog(Animal):
    def talk(self):
        return 'Woof! Woof!'

# 实例化一个Cat、一个Dog
animals = [Cat('Missy'), Dog('Lassie')]

for animal in animals:
    print("{} : {}".format(animal.name, animal.talk()))

用Python实现多态

3. Python类的相关知识

3.1 字段(变量)

① 普通字段属于对象、静态字段属于类。

② 普通字段需要通过对象来访问、静态字段通过类访问。

③ 静态字段在内存中只保存一份、普通字段在每个对象中都要保存一份。

因此:通过类创建对象时,如果每个对象都具有相同的字段,那么就应该使用静态字段。

3.2 方法

方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

① 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self。

② 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls。

③ 静态方法:由类调用;无默认参数。

class Animal(object):
    def __init__(self, name):
        self.name = name
        self.num = None

    def say_hi(self):   # 普通方法,由实例调用访问实例变量
        print("Hi~ {}".format(self.name))

    @classmethod    # 类方法,不能访问实例变量
    def talk(cls):
        print(" is talking.")

    @staticmethod   # 静态方法,不能访问类变量及实例变量
    def walk():
        print("{} is walking.")

相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。

不同点:方法调用者不同、调用方法时自动传入的参数不同。

3.3 属性

class Animal(object):
    def __init__(self, name):
        self.name = name
        self.num = None

    @property   # 把方法变成属性,可以调用实例变量
    def habit(self):
        return "{}'s habit is eating.".format(self.name)

    @property   # 定义类属性
    def total_animals(self):
        return self.num

    @total_animals.setter   # 给类属性赋值
    def total_animals(self, num):
        self.num = num
        print("total animals: {}".format(self.num))

    @total_animals.deleter  # 删除类属性
    def total_animals(self):
        del self.num
        print("total animals is deleted.")

# 访问habit属性
a = Animal("tommie")

# 访问类属性,调用时不需要加括号
print(a.habit)
a.say_hi()

# 打印类属性
print(a.total_animals)

# 给类属性赋值
a.total_animals = 10
print(a.total_animals)

# 删除类属性
del a.total_animals
try:
    print(a.total_animals)
except AttributeError as e:
    print(e)

==============================================

output:

tommie's habit is eating.
Hi~ tommie
None
total animals: 10
10
total animals is deleted.
'Animal' object has no attribute 'num'

实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:

① 根据用户请求的当前页和总数据条数计算出 m 和 n。

② 根据 m 和 n 去数据库中请求数据。

# ############### 定义 ###############
class Pager:

    def __init__(self, current_page):
        # 用户当前请求的页码(第3页、第7页...)
        self.current_page = current_page
        # 每页默认显示10条数据
        self.per_items = 10 

    @property
    def start(self):
        val = (self.current_page - 1) * self.per_items
        return val

    @property
    def end(self):
        val = self.current_page * self.per_items
        return val

# ############### 调用 ###############

p = Pager(1)
p.start 就是起始值,即:m
p.end   就是结束值,即:n

example code

"""
静态字段方式设置类属性
"""

class Foo(object):

    def bar(self):
        return "john"

    # *必须两个参数
    def set_bar(self, value):
        print("set value:{}".format(value))

    def del_bar(self):
        print("delete value")

    BAR = property(bar, set_bar, del_bar, "description")

obj = Foo()

print(obj.BAR)              # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex"            # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
del Foo.BAR               # 自动调用第三个参数中定义的方法:del_bar方法
print(obj.BAR.__doc__)      # 自动获取第四个参数中设置的值:description...

静态字段方式设置类属性

4. 反射

"""
贯穿开发周期内都会用到的:hasattr,setattr,getattr,delattr的介绍
传说中的反射,通过名字的字符串获取相应对象的内存地址
"""

import sys

class WebServer(object):
    def __init__(self, host, post):
        self.host = host
        self.post = post

    def start(self):
        print("Server is starting...")

    def stop(self):
        print("Server is stopping...")

    def restart(self):
        self.stop()
        self.start()

# 定义一个类外面的方法
def test_run(res):
    print("{} {} is running...".format(res.host, res.post))

if __name__ == "__main__":
    server = WebServer("localhost", 33)
    # 判断实例中是否有命令行参数同名的方法名
    if hasattr(server, sys.argv[1]):
        func = getattr(server, sys.argv[1])    # 获取对应类方法的内存地址
        # 执行上面获取的方法,可带参数。
        func()

    # setattr   # 把一个类外面的方法绑定到一个类对象中
    setattr(server, "run", test_run)
    server.run(server)

    # delattr   # 删除类方法
    delattr(WebServer, "stop")
    print("=======" * 10)
    server.restart()

5.类的特殊成员

"""
类的特殊成员
"""

class A(object):
    """
    这是一个测试的类。。。
    """
    pass

# __doc__ 表示类的描述信息
print(A.__doc__)

# __module__ 表示当前操作的对象在那个模块
a = A()
print(A.__module__)    # __main__
print(a.__module__)    # __main__

# __class__ 表示当前操作的对象的类是什么
print(a.__class__)  # <class '__main__.A'>

# __init__ 构造方法,通过类创建对象时,自动触发执行

# __del__ 析构方法,当对象在内存中被释放时,自动触发执行。?用于关闭构造方法中打开的文件或数据库?

# __call__ 实例对象后面加括号直接执行
# 构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

Python之路Day7的更多相关文章

  1. Python之路,Day7 - Python基础7 面向对象

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...

  2. python之路-Day7

    编程范式 编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方 ...

  3. Python之路

    Python学习之路 第一天   Python之路,Day1 - Python基础1介绍.基本语法.流程控制              第一天作业第二天   Python之路,Day2 - Pytho ...

  4. Python之路,Day7 - 面向对象编程进阶

    本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 经典类vs新式类 把下面代 ...

  5. python学习之路-day7

    本节内容: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 面向对象高级语法部分 静态方法                             ...

  6. Python之路【第一篇】python基础

    一.python开发 1.开发: 1)高级语言:python .Java .PHP. C#  Go ruby  c++  ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...

  7. Python之路第一课Day7--随堂笔记(面向对象编程进阶...未完待续 )

    本节内容: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 一.静态方法 通过@s ...

  8. python之路七

    静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量 ...

  9. python之路 目录

    目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...

随机推荐

  1. ThinkPHP第十四天(显示TRACE界面配置,关联模型详解定义)

    1.显示TRACE界面,首选需要在显示模版界面,$this->display(),然后需要在配置文件中配置 SHOW_PAGE_TRACE => true 2.关联模型使用 主表以user ...

  2. 【转】VPN服务器配置详解

    参考博文: VPN服务器配置详解   等公司上服务器开始配置 vpn

  3. 自己动手写List集合(C#)

    平时经常使用微软的List集合,觉得理所应当,这阵子突然意识到学编程学这么久,总不能只生存在某个平台某种语言下面.我觉得要跳出这个框,而数据结构是经常用到的,所以呢,作为一个有志向的程序员应该学会它. ...

  4. MVC-05 Model(2)

    五.使用Code First数据库迁移 当Entity Framework Code First的数据模型发生异动时,默认会引发一个System.InvalidOpertaionException异常 ...

  5. Libev学习笔记2

    这一节根据官方文档给出的简单示例,深入代码内部,了解其实现机制.示例代码如下: int main (void) { struct ev_loop *loop = EV_DEFAULT; ev_io_i ...

  6. 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题

    [HDU  3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...

  7. < high performance web sites > 阅读小记

    high performance web sites 1,减少HTTP请求数 (1)图片加载使用image maps 或者 CSS Sprite (2)使用非http协议,如(ftp:, file: ...

  8. android经常使用的电话操作

    给大家分享一下我的一个Android工具类,能够获取手机里面的各种信息,包含拨打电话. 获取全部联系人姓名及电话,插入联系人姓名及电话,插入联系人姓名及电话.插入通话记录.获取用户全部短信.批量插入短 ...

  9. xampp中mysql设置密码

    发现网上的解决办法都比较过时.嗯,解决办法很简单. 打开浏览器localhost:[port]/phpmyadmin/ 点击用户账户选项 选择用户名为root,Host name为localhost也 ...

  10. iOS中的 SB和XIB的前世今生

    今天给大家介绍一下Apple开发中三种几种常用的应用程序编写方式:纯代码创建.使用storyboard/XIB.我们都知道,纯代码编写模式适合大型项目大规模使用,利于版本管理.追踪改动以及代码合并,代 ...