上篇内容回顾和补充

  • 面向对象三大特性

    • 封装

    • 继承

    • 多态

      • 在python中没有多态的概念
      • 变量的类型允许为多种数据类型称之为多态
      # c#/java中的多态
      # 伪代码
      def func(int arg):
      print(arg)
      func(123) # 这样调用是没问题的
      func("aa") # 这样是会报错的,因为func接受的参数必须是int类型 那么如果func函数中的arg参数需要接受多种类型的参数,就需要按照下面的代码来搞:
      class A:
      pass class B(A):
      pass class C(A):
      pass 调用的时候:
      # arg参数,必须是A类型或A的子类类型
      def func(A arg):
      print(arg) # 下面这三种方式都可以赋值给func函数
      # obj = B()
      # obj = C()
      # obj = A() func(obj)

面向对象中的成员

字段

  • 静态字段(类变量,多个对象共用一个字段,主要用于对象的变量内容都一样的时候)
  • 普通字段(对象变量)
  • 注意:静态字段在代码加载时就被创建了,而普通字段在类被实例化的时候才会被创建
class Foo:
CC = 123 # 这个被称为字段(静态字段,属于类) def __init(self):
self.name = "aaa" #这个被称为字段(普通字段,属于对象)
  • 静态字段和普通字段的使用
class Province:
def __init__(self, name):
self.name = name
self.country = "中国" # 实例化类
hn = Province("河南")
hn = Province("河北")
hn = Province("山东")
# 比如我需要实例化1000个像上面的对象,
每个对象中都会存在一个self.country="中国"的变量,
这样就会造成内存的浪费,这个时候就需要用静态字段来搞,代码如下: class Province:
country = "中国"
def __init__(self, name):
self.name = name # 实例化类
hn = Province("河南")
hn = Province("河北")
hn = Province("山东")
# 这样所有的对象就会共用一个类变量country
  • 普通字段和静态字段的访问规则

    • 普通字段只能用对象访问
    • 静态字段用类访问(万不得已的时候可以使用对象访问)

方法

  • 普通方法,至少一个self,由对象执行
class Province:
country = "中国" def __init__(self, name):
self.name = name def show(self): # 普通方法,由对象去调用执行(方法属于类)
print(self.name) # 调用普通方法
p = Province() # 实例化成一个对象
p.show() # 调用对象的show方法
  • 静态方法,使用staticmethod装饰器将该方法变为静态方法,由类直接调用执行(也可以用对象执行,轻易不要用)
class Province:
country = "中国" def __init__(self, name):
self.name = name @staticmethod
def show(arg1, arg2): # 静态方法 == 函数,放在这个位置,表示这个静态方法是跟Province类有关的
print(arg1, arg2) # 执行静态方法
Province.show(111, 222)
  • 类方法,静态方法的特殊形式,使用classmethod装饰器将该方法变为类方法,由类直接调用执行(也可以用对象执行,轻易不要用)
class Province:
country = "中国" def __init__(self, name):
self.name = name @classmethod
def show(cls): # 类方法,由类调用,最少要有一个参数cls,调用的时候这个参数不用传值,自动将类名赋值给cls
print(cls) # 调用方法
Province.show()

属性

  • 将类中的方法变为一个属性,该属性的调用方法和字段是一样的
# 使用装饰器 property 将一个方法变为属性,在调用改属性的时候不需要加括号调用,代码如下:

class Pager:
"""
计算分页的功能
""" def __init__(self, all_count):
self.all_count = all_count @property
def all_pager(self):
"""
计算需要分几页,比如以每页10条为例子
:return:
"""
a1, a2 = divmod(self.all_count, 10)
if a2 == 0:
return a1
else:
return a1 + 1 p = Pager(101)
ret = p.all_pager
print(ret)
  • 给属性添加赋值、删除功能(第一种方式)
class Pager:
"""
计算分页的功能
""" def __init__(self, all_count):
self.all_count = all_count @property # 将一个方法变为属性
def all_pager(self):
"""
计算需要分几页,比如以每页10条为例子
:return:
"""
a1, a2 = divmod(self.all_count, 10)
if a2 == 0:
return a1
else:
return a1 + 1 @all_pager.setter # 让all_pager属性具有赋值的方法,提供一个关联方式,具体的创建变量的代码还是需要自己去写的
def all_pager(self, value):
print(value) @all_pager.deleter # 让all_pager属性具有删除的方法, 将del和这个方法进行关联,具体的删除方法还是需要自己去写的
def all_pager(self):
print(“del all_pager”) p = Pager(101)
ret = p.all_pager
print(ret) p.all_pager = "100" # 给属性设置参数,会调用被装饰器@all_pager.setter装饰的方法
del p.all_pager # 删除 会调用被装饰器all_pager.deleter 装饰的方法
  • 给属性添加赋值、删除功能(第二种方式)
class Pager:
def __init__(self, all_count):
self.all_count = all_count def f1(self):
return 123 def f2(self, value):
pass def f3(self):
pass foo = property(fget=f1, fset=f2, fdel=f3) # 将foo实例化成一个属性,对foo进行调用的时候执行方法f1,对foo方法进行赋值的时候执行方法f2,对foo进行删除的时候调用方法f3 p = Pager(100)
result = p.foo
print(result) p.foo = "aaa" del p.foo

成员修饰符

  • 私有,任何私有的东西都不能够在本类外部进行调用

    • 私有字段

      • 私有普通字段 只能够在本类中调用,被继承的都不能够被调用
      class Foo:
      def __init__(self, name):
      self.__name = name # 定义一个私有的普通字段 def f1(self):
      print(self.__name) class Bar(Foo):
      def f2(self):
      print(self.__name) # 调用不到私有普通字段
      obj = Foo("aaa")
      print(obj.__name) # 报错,私有字段只能够在本类中的方法进行调用
      obj.f1() # 这个就是正常的
      • 私有静态字段 # 需要将一个方法变成静态方法,在静态方法中调用静态字段,然后在类外面通过调用类的静态方法,就可以访问类中的静态字段了
      class Foo:
      __cc = "123" # 定义一个私有的静态字段 def __init__(self, name):
      self.__name = name @staticmethod
      def f1():
      print(Foo.__cc) # print(Foo.__cc) # 这样调用会报错
      Foo.f1() # 这样就可以了
    • 私有方法

      • 私有普通方法
      class Foo:
      
          def __init__(self, name):
      self.name = name # 定义一个私有的普通字段 def __print(self):
      print(self.name) def f1(self):
      self.__print() obj = Foo("aaa")
      obj.f1() # 通过调用类中的公有方法来执行私有方法
      • 私有静态方法
      class Foo:
      
      	def __init__(self, name):
      self.name = name # 定义一个私有的普通字段 @staticmethod
      def __f2(num):
      print(num) @staticmethod
      def f3(num):
      Foo.__f2(num) Foo.f3(10)
  • 私有属性
  • 使用对象访问私有的字段或方法可以通过obj._类名私有方法 调用类中私有的字段和方法
class Foo:

    """
这是一个测试类
""" def __init__(self, name):
self.name = name
self.__age = 10 def __print(self):
print(self.name) obj = Foo("xx")
print(obj._Foo__age)
obj._Foo__print()

特殊成员

  • __init__ 构造方法,也叫作初始化方法
  • __del__ 析构函数 垃圾回收
  • __doc__ 注释 对类的一个说明文档
class Foo:

    """
这是一个测试类
""" def __init__(self, name):
self.name = name obj = Foo("xx")
print(obj.__doc__) # 输出
这是一个测试类
  • __class__ 返回该对象属于哪个类 使用方法:对象.class
class Foo:

    def __init__(self, name):
self.name = name obj = Foo("xx")
print(obj.__class__) # 输出
<class '__main__.Foo'> # 表示本模块中的Foo类
  • __call__ 执行对象() 会调用__call__方法
class Foo:

    def __init__(self, name):
self.name = name def __call__(self):
print("__call__", self.name) obj = Foo("xx")
obj()
  • __str__ 直接print对象的时候会调用__str__方法,并且会将__str__方法的返回值赋值给obj进行输出
class Foo:

    """
这是一个测试类
""" def __init__(self, name):
self.name = name def __str__(self):
return self.name obj = Foo("xx")
print(obj) # 输出
xx
  • __add__

  • __dict__

class Foo:

    """
这是一个测试类
""" def __init__(self, name, age):
self.name = name
self.__age = age obj1 = Foo("aaa", 100)
obj2 = Foo("bbb", 101) ret = obj1.__dict__
print(ret) # 输出
{'_Foo__age': 100, 'name': 'aaa'}
  • __getitem__ 对字典通过key取值和列表通过切片取值底层的实现

    • 字典通过key取值
    class Foo:
    
        def __init__(self, name, age):
    self.name = name
    self.__age = age def __getitem__(self, item):
    print(item) obj1 = Foo("aaa", 100) obj1["xxx"] # 会调用对象obj1的__getitem__方法 中括号内的参数赋值给item
    obj1[1:2] # 输出
    xxx
    slice(1, 2, None) # slice是一个类
    • 列表通过切片取值

    class Foo: def __init__(self, name, age):
    self.name = name
    self.__age = age def __getitem__(self, item):
    print(type(item))
    print(item)
    print(item.start)
    print(item.stop)
    print(item.step) obj1 = Foo("aaa", 100)
    obj1[1:20:2] # 输出
    <class 'slice'>
    slice(1, 20, 2)
    1
    20
    2
  • __setitem__ 对字典通过key设置值和列表通过切片设置值底层的实现

    • 字典通过key设置值
    class Foo:
    def __init__(self, name, age):
    self.name = name
    self.__age = age def __getitem__(self, item):
    print(type(item))
    print(item)
    print(item.start)
    print(item.stop)
    print(item.step) def __setitem__(self, key, value):
    print(key, value) def __delitem__(self, key):
    print("del", key) obj1 = Foo("aaa", 100)
    obj1["key"] = "value" # 输出
    key value
    • 列表通过切片设置值
    class Foo:
    
        def __init__(self, name, age):
    self.name = name
    self.__age = age def __getitem__(self, item):
    print(type(item))
    print(item)
    print(item.start)
    print(item.stop)
    print(item.step) def __setitem__(self, key, value):
    print(key, value)
    print(key.start)
    print(key.stop)
    print(key.step) def __delitem__(self, key):
    print("del", key) obj1 = Foo("aaa", 100)
    obj1[1:20] = [1, 2, 3] # 输出
    slice(1, 20, None) [1, 2, 3]
    1
    20
    None
  • __delitem__ 删除字典指定的key和列表指定的切片范围底层的实现方法

    • 删除字典指定的key
    class Foo:
    
    def __init__(self, name, age):
    self.name = name
    self.__age = age def __getitem__(self, item):
    print(type(item))
    print(item)
    print(item.start)
    print(item.stop)
    print(item.step) def __setitem__(self, key, value):
    print(key, value)
    print(key.start)
    print(key.stop)
    print(key.step) def __delitem__(self, key):
    print("del", key) obj1 = Foo("aaa", 100)
    del obj1["aaa"] # 输出
    del aaa
    • 删除列表指定的切片范围
    class Foo:
    
    def __init__(self, name, age):
    self.name = name
    self.__age = age def __getitem__(self, item):
    print(type(item))
    print(item)
    print(item.start)
    print(item.stop)
    print(item.step) def __setitem__(self, key, value):
    print(key, value)
    print(key.start)
    print(key.stop)
    print(key.step) def __delitem__(self, key):
    print("del", key)
    print(key.start)
    print(key.stop)
    print(key.step) obj1 = Foo("aaa", 100)
    del obj1[1:20] # 输出
    del slice(1, 20, None)
    1
    20
    None
  • __iter__ 含有该方法,对象就可以被迭代了,默认不可迭代

class Foo:

    def __iter__(self):
yield 1
yield 2 obj = Foo()
for item in obj:
print(item)

面向对象其他

  • isinstance 查看对象是否是类和该类父类的实例

class Foo:
pass obj = Foo() ret = isinstance(obj, Foo)
print(ret) # 输出
True
  • issubclass 查看前者是否是后者的子类
class Foo:
pass class Bar(Foo):
pass ret = issubclass(Bar, Foo)
print(ret) # 输出
Trues
  • 执行父类的方法,在父类方法的基础之上再添加自己的内容
class Foo:

    def f1(self):
print("Foo.f1") class Bar(Foo): def f1(self):
# 主动执行父类的f1方法
super(Bar, self).f1()
print("哈哈哈") obj = Bar()
obj.f1() # 输出
Foo.f1
哈哈哈
  • 应用

    • 自定义类型,对字典进行补充 --> 有序字典
    class MyDict(dict):
    
    def __init__(self):
    self.li = []
    super(MyDict, self).__init__() # 执行父类的__init__方法 def __setitem__(self, key, value):
    self.li.append(key)
    super(MyDict, self).__setitem__(key, value) # 执行父类的__setitem__方法 def __str__(self):
    temp_list = []
    for key in self.li:
    value = self.get(key)
    temp_list.append("'%s': %s" % (key, value,)) temp_str = "{" + ",".join(temp_list) + "}"
    return temp_str obj = MyDict()
    obj["k1"] = 123 # 调用obj的__setitem__方法
    obj["k2"] = 456
    print(obj) # 调用obj的__str__方法

异常处理

  • try except
  • else 如果无异常,则执行
  • finally 不管是否有异常,都执行
  • raise 主动触发异常
  • assert 断言 条件成立不报错,反之报错

设计模式之单例模式

单例模式就是一个类只能创建一个实例化对象


class Foo:
instance = None def __init__(self, name):
self.name = name @classmethod
def get_instance(cls):
if cls.instance:
return cls.instance
else:
obj = cls("aaa")
cls.instance = obj
return obj obj1 = Foo.get_instance()
print(obj1) obj2 = Foo.get_instance()
print(obj2) # 输出
<__main__.Foo object at 0x1007f9550>
<__main__.Foo object at 0x1007f9550>

python学习之路-8 面向对象之进阶的更多相关文章

  1. Python学习之路10☞面向对象进阶

    一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 class Foo(objec ...

  2. Python学习之路9☞面向对象的程序设计

    一 面向对象的程序设计的由来 见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 二 什么是面向对象的程序设计及为什么要有它 面向过 ...

  3. Python学习之路——类-面向对象编程

    类 面向对象编程 通过类获取一个对象的过程 - 实例化 类名()会自动调用类中的__init__方法 类和对象之间的关系? 类 是一个大范围 是一个模子 它约束了事务有哪些属性 但是不能约束具体的值 ...

  4. python学习之路------你想要的都在这里了

    python学习之路------你想要的都在这里了 (根据自己的学习进度后期不断更新哟!!!) 一.python基础 1.python基础--python基本知识.七大数据类型等 2.python基础 ...

  5. Python学习之路【第一篇】-Python简介和基础入门

    1.Python简介 1.1 Python是什么 相信混迹IT界的很多朋友都知道,Python是近年来最火的一个热点,没有之一.从性质上来讲它和我们熟知的C.java.php等没有什么本质的区别,也是 ...

  6. python学习之路-day2-pyth基础2

    一.        模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,第三方库存放位置:site-packages sys模块简介 导入模块 import sys 3 sys模 ...

  7. Python学习之路-Day2-Python基础3

    Python学习之路第三天 学习内容: 1.文件操作 2.字符转编码操作 3.函数介绍 4.递归 5.函数式编程 1.文件操作 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个 ...

  8. Python学习之路-Day2-Python基础2

    Python学习之路第二天 学习内容: 1.模块初识 2.pyc是什么 3.python数据类型 4.数据运算 5.bytes/str之别 6.列表 7.元组 8.字典 9.字符串常用操作 1.模块初 ...

  9. Python学习之路-Day1-Python基础

    学习python的过程: 在茫茫的编程语言中我选择了python,因为感觉python很强大,能用到很多领域.我自己也学过一些编程语言,比如:C,java,php,html,css等.但是我感觉自己都 ...

随机推荐

  1. HDOJ/HDU 2544 最短路---dijkstra算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 这题的思路可以见这里(同一类型):http://blog.csdn.net/xiaozhuaix ...

  2. git 学习笔记一

    1.git的 介绍 分布式和 集中式 集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟, ...

  3. CSS基础知识笔记(二)之选择器

    CSS选择器 选择器{ 样式; } 每一条css样式声明(定义)由两部分组成,形式如下: 在{}之前的部分就是“选择器”,“选择器”指明了{}中的“样式”的作用对象,也就是“样式”作用于网页中的哪些元 ...

  4. javascript将毫秒还原为可读时间格式

    <script type="text/javascript"> //随便设置一个时间 var otime = new Date("2015-11-11 20: ...

  5. .net的WebForm模拟MVC进行模型绑定,让自己少操劳

    一.前言 用过MVC的兄弟们都知道,MVC有模型绑定表单提交的数据功能,那么我也想偷个懒也写个WebForm版的模型绑定.这里主要定义一个泛型方法,然后通过反射把表单上对应属性名字的值赋值到反射创建类 ...

  6. 使用CMD连接SQL Server

      在CMD中操作数据库,界面不美观,而且排版不整齐,但在机器上没有安装SQLSERVER的时候,也是极其方便的.   在命令行中输入 OSQL ?可以获得所有帮助信息   osql -S 数据库服务 ...

  7. http断点续传原理

    断点续传一是断点,一续传. 断点是在下载时,将下载文件分多片,同时进行多片一起下载,如果任务被暂停,暂停的位置就是断点. 续传就是未完成的下载再次开始时,会从上次的断点继续传送. 在下载(或上传)过程 ...

  8. 为自己的Android应用添加广告

    平时也写了不少Android小应用,但是都是做练习之用,从来没有想过添加广告赚钱这一说. 个人是非常反感在应用内添加广告这种行为的,非常影响用户体验,不小心点到广告的话,手机流量哗哗地就没了··· 但 ...

  9. 加载gif图过渡效果

    加载gif图片,过渡效果: 调用: - (id)initWithGifView:(UIView *)view { self = [super initWithView:view]; if (self) ...

  10. js中的因数分解

    方法一: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8& ...