Python类的定义继承调用比较方法技巧

目录
  • 一、类的约束
  • 二、类的定义
    • 2.1、创建创建
      • 2.1.1、类的导入
      • 2.1.2、构造器
      • 2.1.3、类属性
  • 三、类的继承
    • 3.1、单继承
    • 3.2、多继承
    • 3.3、调用父类方法
    • 3.4、属性扩展
      • 3.4.1、完全扩展
      • 3.4.2、单独扩展
  • 四、类的调用
  • 五、抽象类
    • 5.1、强制类型检查
  • 六、类的比较

一、类的约束

# _开头: 私有变量;
# __开问: 私有变量,不能被继承;
# __xxx__: 能被访问,不能被继承;
class A:
def __init__(self):
self._internal = 0 # 私有变量不能被访问
self.public = 1 # 可被访问
def public_method(self):
pass
def _private_method(self): # 私有方法不能被访问
pass
class B:
def __init__(self):
self.__private = 0 # 这个属性会在内存中被重新命名为_B__private

def __private_method(self): # 不能被访问,不能被继承
pass
def __private_method__(self): # 能被访问,不能被继承
pass

二、类的定义

2.1、创建创建

class Dog:
a = "0"; #相当于public static变量,全局的
"""__init__是一个默认的方法,且self为默认的,用self修饰的属性为public类型的类变量"""
def __init__(self, name, age):
self.name = name
self.age = age
self.sex = "1";#设置属性默认值

def sit(self):
print(self.name + "is now sitting" + "and sex is " + self.sex + Dog.a)

@classmethod
def user_name(cls, name): #注意这种注解的用法
return cls()

dog = Dog("kk", 12);
dog.sit()

2.1.1、类的导入

在python中分为文件、模块、类,其中文件和模块可划等价;所以导入有几种方式,比如dog.py文件中定义了两个Class,则在使用类中导入方法有以下几种:

  • from car import Dog;#导入一个模块中的特定类,使用时则直接Car();
  • import car;#导入一个模块中的所有类,使用时则需要car.Car();
  • from car import *;#不推荐,容易引起命名冲突问题
from collections import OrderedDict; #使用标准类库
t = OrderedDict();

2.1.2、构造器

class Date:
# Primary constructor
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day

# Alternate constructor
@classmethod
def today(cls):
t = time.localtime() #它接收一个class作为第一个参数,它被用来创建并返回最终的实例, 这个cls==__init__
return cls(t.tm_year, t.tm_mon, t.tm_mday)

a = Date(2020, 5, 10) # Primary
b = Date.today() # Alternate

减少构造函数的参数个数:

class Structure1:
# Class variable that specifies expected fields
_field_list = []

def __init__(self, *args):
if len(args) != len(self._field_list):
raise TypeError(f'Expected {len(self._field_list)} arguments')
# Set the arguments
for name, value in zip(self._field_list, args):
setattr(self, name, value)

# Example class definitions
class Course(Structure1):
# 这行只是为了一个准许入判断,没有太多实际意思,或是一个声明
_field_list = ['course_name', 'total_class', 'score']

c = Course('python', 30, 0.3);

关键字参数

class Structure2:
_field_list = []

def __init__(self, *args, **kwargs):
if len(args) > len(self._field_list):
raise TypeError(f'Expected {len(self._field_list)} arguments')
# Set all of the positional arguments
for name, value in zip(self._field_list, args):
setattr(self, name, value)

# Set the remaining keyword arguments
#是通过pop这种方式来检查的,在长度范围内如果pop出错则抛异常
for name in self._field_list[len(args):]:
setattr(self, name, kwargs.pop(name))

# Check for any remaining unknown arguments
if kwargs:
raise TypeError(f"Invalid argument(s): {','.join(kwargs)}")

# Example use
class Course(Structure2):
_field_list = ['course_name', 'total_class', 'score']

course_1 = Course('python', 30, 0.3)
course_2 = Course('python', 30, score=0.3)
course_3 = Course('python', total_class=30, score=0.3)

扩展关键字参数:

class Structure3:
# Class variable that specifies expected fields
_field_list = []

def __init__(self, *args, **kwargs):
if len(args) != len(self._field_list):
raise TypeError(f'Expected {len(self._field_list)} arguments')

# Set the arguments
for name, value in zip(self._field_list, args):
setattr(self, name, value)

# Set the additional arguments (if any)
extra_args = kwargs.keys() - self._field_list
for name in extra_args:
setattr(self, name, kwargs.pop(name))

if kwargs:
raise TypeError(f"Duplicate values for {','.join(kwargs)}")

# Example use
if __name__ == '__main__':
class Course(Structure3):
_field_list = ['course_name', 'total_class', 'score']

course_1 = Course('python', 30, 0.3)
course_2 = Course('python', 30, 0.3, date='8/5/2020')

2.1.3、类属性

要创建一个新的实例属性,可以通过描述器的形式来定义它的功能,一个描述器就是一个实现了3个核心属性访问操作的类,分别对应get\set\delete这三个特殊的方法。

# Descriptor attribute for an integer type-checked attribute
class Integer:
def __init__(self, name):
self.name = name
"""下面三个方法只是一个更严格的定义,可以不需要,要使用上面的描述器,需要把描述器放入到一个class中,这样所有对描述器的访问都会被get/set/delete所捕获"""
def __get__(self, instance, cls):
if not instance:
return self
else:
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, int):
raise TypeError('Expected an int object')
instance.__dict__[self.name] = value
def __delete__(self, instance):
del instance.__dict__[self.name]

示例1:

class Point:
"""实例变量,和下面的x,y不是一回事"""
x = Integer('x')
y = Integer('y')

def __init__(self, x, y):
self.x = x
self.y = y
print(Point.x.name) # x
point = Point(3, 5)
print(f'point x = {point.x}') #3
print(f'point y = {point.y}') #5
point.y = 6
print(f'after change,point y = {point.y}') #6

三、类的继承

ptyhon在实现继承时会用一个叫MRO列表的算法实现,它有三条规则:1、子类会先于父类;2、多个父类会根据它们在列表中的顺序被检查;3、如果对下一个类有两个合法的选择,则返回第一个合法的父类;

3.1、单继承

class A:
def __init__(self):
self.x = 0
class B(A):
def __init__(self):
super().__init__() #这行需要注意,也可以不写,但不写时就不会调用父类的init方法
self.y = 1

3.2、多继承

class Base:
def __init__(self):
print('call Base.__init__')
class A(Base):
def __init__(self):
Base.__init__(self)
print('call A.__init__')

class B(Base):
def __init__(self):
Base.__init__(self)
print('call B.__init__')
"""多继承的实现"""
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print('call C.__init__')
c = C()
# call Base.__init__
# call A.__init__
# call Base.__init__
# call B.__init__
# call C.__init__

3.3、调用父类方法

class Proxy:
def __init__(self, obj):
self._obj = obj

def __getattr__(self, name):
return getattr(self._obj, name)

def __setattr__(self, name, value):
if name.startswith('_'):
"""调用父类方法"""
super().__setattr__(name, value)
else:
setattr(self._obj, name, value)

proxy = Proxy({})
proxy.__setattr__("_name", "hm")

3.4、属性扩展

3.4.1、完全扩展

# 父类
class Person:
def __init__(self, name):
self.name = name

# defined Getter function, auto to call the sign name.setter when it be build
@property
def name(self):
return self._name

# defined Setter function
@name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError('Expected a string')
self._name = value

# defined Deleter function
@name.deleter
def name(self):
raise AttributeError("Can't delete attribute")

"""子类"""
class SubPerson(Person):
@property
def name(self):
print('Getting name')
return super().name

@name.setter
def name(self, value):
print(f'Setting name to {value}')
super(SubPerson, SubPerson).name.__set__(self, value)

@name.deleter
def name(self):
print('Deleting name')
super(SubPerson, SubPerson).name.__delete__(self)

"""测试"""
sub_person = SubPerson('Guido')
print(f'name is: {sub_person.name}')

3.4.2、单独扩展

class SubPerson(Person):
@Person.name.getter
def name(self):
print('Getting name')
return super().name # or super(SubPerson, SubPerson).name.__set__(self, value)
sub_p = SubPerson('Bill')
#不能用property的原因是,property其实是get、set、del函数的集合,各有各的用处。下面才是正确的扩展方式,所以下面的代码是不工作的
class SubPerson(Person):
@property # Doesn't work
def name(self):
print('Getting name')
return super().name
#如果要用property属性则要用下面的编码实现
class SubPerson(Person):
@property
def name(self):
print('Getting name')
return super().name
@name.setter
def name(self, value):
print(f'Setting name to {value}')
super(SubPerson, SubPerson).name.__set__(self, value)
@name.deleter
def name(self):
print('Deleting name')
super(SubPerson, SubPerson).name.__delete__(self)

四、类的调用

import time
class Date:
# Primary constructor
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
# Alternate constructor
@classmethod
def today(cls):
t = time.localtime() #它接收一个class作为第一个参数,它被用来创建并返回最终的实例, 这个cls==__init__
return cls(t.tm_year, t.tm_mon, t.tm_mday)
"""普通调用"""
c = Date(2010, 12, 12)

"""类方法在继承中使用"""
class NewDate(Date):
pass
c = Date.today() # Creates an instance of Date (cls=Date)
d = NewDate.today() # Creates an instance of NewDate (cls=NewDate)

五、抽象类

from abc import ABCMeta, abstractmethod
class IStream(metaclass=ABCMeta):
@abstractmethod
def read(self, max_bytes=-1):
pass
@abstractmethod
def write(self, data):
pass
"""不能被实例化"""
#a = IStream()

class SocketStream(IStream):
def read(self, max_bytes=-1):
pass
def write(self, data):
pass
"""检查"""
def serialize(obj, stream):
if not isinstance(stream, IStream):
raise TypeError('Expected an IStream')
pass

5.1、强制类型检查

from abc import ABCMeta, abstractmethod
class IStream(metaclass=ABCMeta):
@abstractmethod
def read(self, max_bytes=-1):
pass
@abstractmethod
def write(self, data):
pass
import io
# Register the built-in I/O classes as supporting our interface
IStream.register(io.IOBase)

# Open a normal file and type check
f = None #open('test.txt')
print(f'f object is IStream type: {isinstance(f, IStream)}')
#f object is IStream type: False

六、类的比较

from functools import total_ordering
class Room:
def __init__(self, name, length, width):
self.name = name
self.length = length
self.width = width
self.square_feet = self.length * self.width
@total_ordering
class House:
def __init__(self, name, style):
self.name = name
self.style = style
self.rooms = list()
@property
def living_space_footage(self):
return sum(r.square_feet for r in self.rooms)
def add_room(self, room):
self.rooms.append(room)
def __str__(self):
return f'{self.name}: {self.living_space_footage} square foot {self.style}'
def __eq__(self, other):
return self.living_space_footage == other.living_space_footage

def __lt__(self, other):
return self.living_space_footage < other.living_space_footage
# Build a few houses, and add rooms to them
h1 = House('h1', 'Cape')
h1.add_room(Room('Master Bedroom', 14, 21))
h1.add_room(Room('Living Room', 18, 20))
h1.add_room(Room('Kitchen', 12, 16))
h1.add_room(Room('Office', 12, 12))

h2 = House('h2', 'Ranch')
h2.add_room(Room('Master Bedroom', 14, 21))
h2.add_room(Room('Living Room', 18, 20))
h2.add_room(Room('Kitchen', 12, 16))

h3 = House('h3', 'Split')
h3.add_room(Room('Master Bedroom', 14, 21))
h3.add_room(Room('Living Room', 18, 20))
h3.add_room(Room('Office', 12, 16))
h3.add_room(Room('Kitchen', 15, 17))
houses = [h1, h2, h3]

print(f'Is {h1} bigger than {h2}: {h1 > h2}')
print(f'Is {h2} smaller than {h3}: {h2 < h3}')
print(f'Is {h2} greater than or equal to {h1}: {h2 >= h1}')
print(f'Which one is biggest in houses: {max(houses)}')
print(f'Which is smallest in houses: {min(houses)}')

""""""
# Is h1: 990 square foot Cape bigger than h2: 846 square foot Ranch: True
# Is h2: 846 square foot Ranch smaller than h3: 1101 square foot Split: True
# Is h2: 846 square foot Ranch greater than or equal to h1: 990 square foot Cape: False
# Which one is biggest in houses: h3: 1101 square foot Split
# Which is smallest in houses: h2: 846 square foot Ranch
# """"""
class House:
def __eq__(self, other):
pass
def __lt__(self, other):
pass
# Methods created by @total_ordering
__le__ = lambda self, other: self < other or self == other
__gt__ = lambda self, other: not (self < other or self == other)
__ge__ = lambda self, other: not (self < other)
__ne__ = lambda self, other: not self == other

到此这篇关于Python类的定义继承调用比较方法技巧的文章就介绍到这了,更多相关Python类的定义内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-06-23

Python类的继承与多态详细介绍

目录 概念 类的创建 类的继承 多态的使用 概念 类(Class): 用来描述具有相同的属性和方法的对象的集合. 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中且在函数体之外.类变量通常不作为实例变量使用. 类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用 self:self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类. 类调用 Car.weight 实例化  car01=Car(5) 实例对象调用  car01

python基础之定义类和对象详解

定义简单的类 面向对象是更大的封装,在一个类中封装多个方法,这样通过这个类创建出来的对象,就可以直接调用这些方法了! 定义只包含方法的类 在python中,要定义一个只包含方法的类,语法格式如下: #用class定义类名 class 类名: def 方法1(self,参数列表) #方法的属性中有且仅有一个self pass def 方法2(self,参数列表) #类之外定义的def是函数,在类里面定义的def叫做方法,而且括号里必须要有self pass class Student: pass

python中的3种定义类方法

目录 1.普通方法 2.类方法 3.静态方法 4.总结 python中的3种定义类方法: 普通方法 类方法(@classmethod) 类方法(@classmethod) 1.普通方法 创建普通的方法的方式有两种(class A() & class B()). class A(): def __init__(self, name, age): self.name = name self.age = age def get_name(self): print('my name is', self.

Python枚举类定义和使用方法

一些具有特殊含义的类,其实例化对象的个数往往是固定的,比如用一个类表示月份,则该类的实例对象最多有 12 个:再比如用一个类表示季节,则该类的实例化对象最多有 4 个. 针对这种特殊的类,Python 3.4 中新增加了 Enum 枚举类.也就是说,对于这些实例化对象个数固定的类,可以用枚举类来定义. 例如,下面程序演示了如何定义一个枚举类: from enum import Enum class Color(Enum): # 为序列值指定value值 red = 1 green = 2 blu

Python自定义对象实现切片功能

目录 1.魔术方法:__getitem__() 2.自定义序列实现切片功能 3.自定义字典实现切片功能 切片是 Python 中最迷人最强大最 Amazing 的语言特性(几乎没有之一),在<Python进阶:切片的误区与高级用法>中,我介绍了切片的基础用法.高级用法以及一些使用误区.这些内容都是基于原生的序列类型(如字符串.列表.元组--),那么,我们是否可以定义自己的序列类型并让它支持切片语法呢?更进一步,我们是否可以自定义其它对象(如字典)并让它支持切片呢? 1.魔术方法:__getit

Python类的定义和使用详情

目录 1.基础概念 2.定义一个Person类 3.类定义 4.类方法定义 5.类的继承 6.类的公有,私有 7.子类调用父类的方法 1.基础概念 在面向对象的程序设计过程中有两个重要概念:类(class)和对象(object,也被称为实例,instance),其中类是某一批对象的抽象,可以把类理解成某种概念:对象才是一个具体存在的实体.从这个意义上看,日常所说的人,其实都是人的对象,而不是人类. Python 定义类的简单语法如下: class 类名:    执行语句...    零个到多个类

python调用stitcher类自动实现多个图像拼接融合功能

使用stitcher需要注意,图像太大会报错而且计算慢. 特点和适用范围:图像需有足够重合相同特征区域. 优点:适应部分倾斜/尺度变换和畸变情形,拼接效果好,使用简单,可以一次拼接多张图片. 缺点:需要有足够的相同特征区域进行匹配,速度较慢(和图像大小有关). 原图(可下载) 代码(两张图片拼接) import sys import cv2 if __name__ == "__main__": img1 = cv2.imread('C:/Users/Guaguan/Desktop/im

python中让自定义的类使用加号&quot;+&quot;

目录 1.python的魔法方法__add__() 2.对CartoonImage重载“+” 2.1实现CartoonImage类 3.测试“+”是否能实现图像拼接 3.1对CartoonImage对象使用“+”操作 如果代码是“1+1”,那么python控制台必然输出2,这很符合我们对“数值类”的认识,“+”运算符必然能对数值进行加法. 假设自己现在想设计一个称为“动漫图片CartoonImage类”,能不能实现它的对象之间的“+”操作呢?比如想要对两个动漫图像对象cartoon_1和cart

关于Python中定制类的比较运算实例

Python中的比较运算有几种:小于.小于等于.等于.大于等于.大于.不等于等.如果我们的数据对象具有明确的物理含义,比如说数值是带有数字与物理单位的字符串组合,那么进行大小比较的时候就可以做此定制. 下面针对6种比较方法中的一种来进行定制示范,选择小于判断来做尝试. 写如下示范代码: class myClass: def __init__(self,value): self.value = value def __lt__(self,other): return int(self.value[

Python自定义指标聚类实例代码

目录 前言 与KMeans++比较 Yolo检测框聚类 总结 前言 最近在研究 Yolov2 论文的时候,发现作者在做先验框聚类使用的指标并非欧式距离,而是IOU.在找了很多资料之后,基本确定 Python 没有自定义指标聚类的函数,所以打算自己做一个 设训练集的 shape 是 [n_sample, n_feature],基本思路是: 簇中心初始化:第 1 个簇中心取样本的特征均值,shape = [n_feature, ]:从第 2 个簇中心开始,用距离函数 (自定义) 计算每个样本到最近中

Django自定义manage命令实例代码

manage.py是在我们创建Django项目的时候就自动生成在根目录下的一个命令行工具,它可以执行一些简单的命令,其功能是将Django project放到sys.path目录中,同时设置DJANGO_SETTINGS_MODULE环境变量为当前project的setting.py文件. manage.py的代码是这样的: #!/usr/bin/env python import os import sys if __name__ == "__main__": os.environ.

微信公众号测试账号自定义菜单的实例代码

自定义菜单接口可实现多种类型按钮,如下: 1.click:点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互: 2.view:跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息. 3.scancode_push:扫码推事件 用户点击按钮后,微信客户

Python ldap实现登录实例代码

下面一段代码是小编给大家介绍的Python ldap实现登录实例代码,一起看看吧 ldap_config = { 'ldap_path': 'ldap://xx.xx.xx.xx:389', 'base_dn': 'ou=users,dc=ledo,dc=com', 'ldap_user': 'uid=reporttest,ou=users,dc=ledo,dc=com', 'ldap_pass': '111111.0', 'original_pass': '111111.0' } ldap_m

python+matplotlib演示电偶极子实例代码

使用matplotlib.tri.CubicTriInterpolator.演示变化率计算: 完整实例: from matplotlib.tri import ( Triangulation, UniformTriRefiner, CubicTriInterpolator) import matplotlib.pyplot as plt import matplotlib.cm as cm import numpy as np #---------------------------------

python的re正则表达式实例代码

本文研究的主要是python的re正则表达式的相关内容,具体如下. 概念:正则表达式(通项公式)是用来简洁表达一组字符串的表达式.优势是简洁,一行胜千言. 应用:字符串匹配. 实例代码: CODEC = 'UTF-8' #encoding:utf-8 import re p=re.compile("ab") str = "abfffa" #match必须匹配首字母 if p.match(str): print p.match(str).group() #match必

Python编程求质数实例代码

本文研究的主要是Python编程求质数实例,选取了几个数进行了测试,具体如下. 定义:质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数. 我们知道自然数(除了0和1以外)都可以写成几个质数相乘再乘以一的格式,所以我们可以用以个数去试一试看看它能否将小于它的质数整除. 首先我们创建一个空的list,然后我们知道2是最小的质数,于是我们把2添加进这个空白的list,之后我们开始循环,第一个数从3开始,用3除以小于3的质数,没有小于它的质数能被它整除,

python模块之paramiko实例代码

本文研究的主要是python模块之paramiko的相关用法,具体实现代码如下,一起来看看. paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能.这是一个第三方的软件包,使用之前需要安装. 1 基于用户名和密码的 sshclient 方式登录 # 建立一个sshclient对象 ssh = paramiko.SSHClient() # 允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面 ssh.set_missing_

简单的python协同过滤程序实例代码

本文研究的主要是python协同过滤程序的相关内容,具体介绍如下. 关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那么通常的做法就是问问周围的朋友,看看最近有什么好的电影推荐.在问的时候,都习惯于问跟自己口味差不多的朋友,这就是协同过滤的核心思想. 这个程序完全是为了应付大数据分析与计算的课程作业所写的一个小程序,先上程序,一共55行.不在意细节的话,55行的程序已经表现出了协同过滤的特性了.就是对每一个用户找4个最接近的用户,然后进行推荐,在选择

python实现Adapter模式实例代码

本文研究的主要是python实现Adapter模式的相关内容,具体实现代码如下. Adapter模式有两种实现方式一种是类方式. #理解 #就是电源适配器的原理吧,将本来不兼容的接口类能够工作 #这个是类实现方式 #例子 #假如一个插座类输出脚是3脚的,而台灯需要的是两脚插座,现在就需要一个Adapter实现适配插座 #Adaptee class socket(object): def Trigle(self): print 'power supply' #target class tableL

python实现Decorator模式实例代码

本文研究的主要是python实现Decorator模式,具体介绍如下. 一般来说,装饰器是一个函数,接受一个函数(或者类)作为参数,返回值也是也是一个函数(或者类).首先来看一个简单的例子: # -*- coding: utf-8 -*- def log_cost_time(func): def wrapped(*args, **kwargs): import time begin = time.time() try: return func(*args, **kwargs) finally: