当前位置: 首页 > news >正文

【python】面向对象(类型定义魔法方法)

目录

一、引言

二、类型定义

1、什么是类型的定义?

2、案例

三、魔法方法

1、什么是魔法方法

2、基础部分

3、比较操作

4、容器类型

5、属性管理

6、封装

7、方法拓展

8、继承

9、多态


一、引言

        Python是一种面向对象的语言,它支持类(class)和对象(object)的概念。面向对象编程是一种程序设计模型,它将程序看作是由对象组成的,这些对象之间通过消息传递来相互通信和协作。

        Python中,类是创建对象的蓝图或模板,它定义了对象的基本结构和行为。对象是类的实例,可以根据类的定义来创建多个实例。每个对象都拥有类中定义的所有属性和方法。

下面是一个简单的Python类和对象的示例:

class Person:  def __init__(self, name, age):  self.name = name  self.age = age  def say_hello(self):  print(f"Hello, my name is {self.name} and I'm {self.age} years old.")  # 创建Person类的实例  
p1 = Person("zs", 25)  
p2 = Person("ls", 30)  # 调用对象的say_hello方法  
p1.say_hello()  # 输出:Hello, my name is Alice and I'm 25 years old.  
p2.say_hello()  # 输出:Hello, my name is Bob and I'm 30 years old.

 

在例子中,我们定义了一个名为Person的类,它有两个属性nameage,以及一个方法say_hello。通过调用Person类的构造函数__init__,我们创建了两个Person对象p1p2,分别代表"zs"和"ls"两个人。然后我们可以通过调用对象的say_hello方法来输出问候语。

面向对象编程的核心概念包括封装、继承、多态和抽象。在Python中,这些概念都有相应的语法和机制来支持。通过使用面向对象编程,我们可以更好地组织和管理代码,使其更易于维护和扩展

二、类型定义

1、什么是类型的定义?

        在编程中,类型是用于描述变量或数据结构的特征和行为的抽象概念。类型定义了变量或数据结构可以存储的数据的类型以及可以执行的操作。通过使用类型,程序员可以确保变量和数据结构中存储的数据是有效的,并且可以在编译时检测到潜在的错误。

        在许多编程语言中,类型可以分为静态类型和动态类型。静态类型在编译时进行类型检查,而动态类型则在运行时进行类型检查。

        静态类型定义了变量或数据结构在编译时必须具有的类型。这种类型通常在声明变量或数据结构时指定,并且不允许在运行时更改。静态类型的优点是编译器可以在编译时捕获许多类型相关的错误,从而提高代码的可靠性和安全性。然而,静态类型也限制了程序员在运行时动态更改变量类型的灵活性。

        动态类型定义了变量或数据结构在运行时可以具有的类型。这种类型可以在运行时更改,并且不需要在声明时指定。动态类型的优点是提供了更大的灵活性,使得程序员可以在运行时根据需要更改变量的类型。然而,动态类型也带来了运行时类型错误的潜在风险,因为它们可能在运行时引发异常或错误。

        类型是编程中的重要概念,用于描述变量和数据结构的特征和行为。它们提供了编译时的类型检查和运行时的灵活性,帮助程序员编写更可靠和可维护的代码。

2、案例

定义一个 dog 类:

class Dog:
"""小狗类定义"""
pass

在 Python 中,首字母大写的名称指的是类。

这个类定义是可以不带 ( ) ,括号中指定的父类型。


给 Dog 类定义属性:

class Dog:
"""小狗类定义"""
name: str = '小黑'
age: int = 3

编写对象,获取对象的属性:

d = Dog()
print(f"name:{d.name},age:{d.age}")

Python 中对于对象的属性是属于动态可变化的。

d = Dog()
d.age = 30
d.gender = '公'
print(f"name:{d.name},age:{d.age},gender:{d.gender}")

也可以给类型添加方法,方法就是定义再类中的函数。

def sit(self):
pass

每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属 性和方法。

def sit(self):
print(f'小狗{self.name}蹲下了')

携带多个参数时,其他的参数放在 self 之后:

def eat(self, food: str):
print(f'小狗{self.name}吃下了{food}')

三、魔法方法

1、什么是魔法方法

        Python中,魔法方法是指那些以双下划线开头和结尾的方法,例如__add__()。这些方法通常用于运算符重载,当对类的某个操作时后端自动调用,而不需要自己直接调用。

如:当使用+将两个数字相加时,在类内部会调用__add__()方法。

2、基础部分

init 被用于初始化实例对象,new方法创建对象后就会调用该方法对实例的属性进行初始化。

class T:
def __init__(self):
self.name = 'sa'
self.pwd = '123'
t = T()

del 是析构方法,当对象的引用计数变为0时,这个对象会被销毁掉,此时就会调用del方法

class T:
def __del__(self):
print("对象被销毁")
t = T()
# t指向0,此前创建的T的实例被销毁
t = 0

call 允许一个类的实例像函数一样被调用,这是一个非常重要的特性

class T:
def __call__(self, *args, **kwargs):
print("类的实例可以像函数一样被调用")
t = T()
t()

len 是内置函数,len(t) 会调用实例的 len 方法

class T:
def __len__(self):
return 100
t = T()
print(len(t))

当被 str() 调用时, 调用该 str 方法

class T:
def __str__(self):
return f"我是{T.__name__}的一个实例"
t = T()
print(t)

bool 可用于逻辑判断部分

class T:
def __init__(self, age):
self.age = age
def __bool__(self):
return self.age > 18
print(bool(T(17) and T(19)))

3、比较操作

        比较操作可以是算术比较(例如等于、不等于、大于、小于、大于等于、小于等于)或者字典比较(例如键在字典中、键不在字典中)。

  1. 算术比较:

    • 等于 (==):eq(self, other)定义等于号的行为。
    • 不等于 (!=):ne(self, other)定义不等号的行为。
    • 大于 (>):gt(self, other)定义大于号的行为。
    • 小于 (<):lt(self, other)定义小于号的行为。
    • 大于等于 (>=):ge(self, other)定义大于等于号的行为。
    • 小于等于 (<=):le(self, other)定义小于等于号的行为。
  2. 字典比较:

    • 键在字典中 (key in dict):如果给定的键在字典中,则返回True,否则返回False。
    • 键不在字典中 (key not in dict):如果给定的键不在字典中,则返回True,否则返回False。

这些比较操作可以用于各种数据类型,包括数字、字符串、列表、元组、集合和字典等。

案例:

class Student:
def __init__(self, age):
self.age = age
def __lt__(self, other):
return self.age < other.age
def __eq__(self, other):
return self.age == other.age
s1 = Student(3)
s2 = Student(3)
print(s1 < s2)
print(s1 == s2)
print(s1 is s2)

4、容器类型

getitem, setitem, delitem getitem

        定义获取容器中指定元素的行为,相当于 self[key], setitem 定义设置容器中指定元素的行 为,相当于 self[key] = value, delitem 定义删除容器中指定元素的行为,相当于 del self[key]。

        字典就是实现了这三个魔法方法,才提供了以[]为基础的操作。

class MyData:
def __init__(self, data=None):
if data is None:
data = set()
self.data = data
def __getitem__(self, item):
return self.data.get(item)
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
my_data = MyData()
my_data['name'] = '小刚'
my_data['age'] = 14
print(my_data['name'])
print(my_data['age'])

如果一个对象实现了 iter , 那么它就是一个可迭代对象

如果既实现 iter 又实现 next ,那么它就是一个迭代器

class Color(object):
def __init__(self):
self.index = -1
self.colors = ['red', 'white', 'black', 'green']
def __iter__(self):
self.index = -1
return self
def __next__(self):
self.index += 1
if self.index >= self.colors.__len__():
raise StopIteration
return self.colors[self.index]
color_object = Color()
# 遍历输出所有颜色
for color in color_object:
print(color)

5、属性管理

class Plane(object):
category = '飞机'
p1, p2 = Plane(), Plane()
# print(p1.category, p1.category)
# Plane.category = '拖拉机'
# print(p1.category, p2.category)
# print(p1.category, p1.category)
# p1.category = '拖拉机'
# print(p1.category, p2.category)

这里主要涉及到了类属性与对象属性实例属性的区别

python中,实例属性存储在一个字典(dict)中,对于属性的操作,都是在操作这个字典

p1.name = 'sa'
print(p1.__dict__)

也可以直接操作这个字典

p1.name = 'sa'
p1.__dict__['pwd'] = '123'
print(p1.pwd)

python中对象的属性为什么可以动态变化?


类属性同样是存储在字典中,只是这个字典是类的字典

可以通过类名和对象名来调用,但是只能通过类名修改,类属性对于该类对象是共享的

类的属性和方法存在在类的 dict 之中

p1, p2 = Plane(), Plane()
print(Plane.__dict__)

属性寻找规则: 先找实例的 dict ,再去查找类的 dict


案例:

class Dog:
name: str = '小黑'
age: int = 3
d1 = Dog()
d1.name = "大黄"
d2 = Dog()
Dog.name = "小白"
print(d1.name)
print(d2.name)

6、封装

        python中,使用一个下划线就等于向使用者宣布这个属性是私有的,但你仍然可以直接对其修改,单个 下划线更像是一种约定,而非技术上的强硬限制。即便使用了双下划线,也仍然有办法直接对其修改, 但这已经不是类所要解决的问题了,一个人执意破坏数据,他总是能找到办法。

案例:

class Stu:
def __init__(self, name, age):
self.__name = name
self.__age = age
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
def get_age(self):
return self.__age
def set_age(self, age):
self.__age = age
stu1 = Stu('小明', 14)
stu2 = Stu('小红', 14)
print(stu1.get_name(), stu1.get_age())
print(stu2.get_name(), stu2.get_age())

还可以通过其他方式来实现封装

class Book:
def __init__(self, price):
self._price = price
@property
def price(self):
return self._price
@price.setter
def price(self, price):
if price > 0:
self._price = price
else:
raise Exception('价格不能为负数')
book = Book(58.5)
print(book.price)
book.price = -1
print(book.price)

使用 @property 装饰器修饰 price 方法后,你就可以像使用属性一样使用 price ,如果你希望可以对 price 进行赋值,那么需要用 @price.setter 装饰器再装饰一个方法,该方法完成对 _price 属性的赋值操 作。 我们以为自己直接操作了对象的属性,但其实我们是在使用类的方法,而且关键的是省去了调用方法时 的那对小括号

7、方法拓展

类方法 : 可以通过类名调用的方法

加上注解,修改参数为 cls (当前类),可以通过 cls 调用类的属性

@classmethod
def run(cls):
print(cls.__name)

静态方法 : 可以通过类名与对象来调用,但是无法使用类变量

@staticmethod
def say():
print("hello world")

8、继承

如果没有指定基类,会默认继承 object 类, object 是所有类的基类,它提供了一些常见方法, 比如 __str__,我们用案例来演示

class Dog(object):
pass

类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类

class A:
pass
class B:
pass
class C(A):
pass
class D(A, B):
pass

查看继承关系

print(D.__bases__)
print(D.__mro__)

继承可以继承属性与方法

class Father:
money = 100
class Son(Father):
pass
s = Son()
print(s.money)
class Father:
money = 100
def hello(self):
print("hello world")
class Son(Father):
pass
s = Son()
s.hello()
class Father:
money = 100
def hello(self):
print("hello world")
class Mother:
money = 200
def cook(self):
print("煮饭")
class Son(Father, Mother):
pass
s = Son()
print(s.money)
s.hello()
s.cook()

当属性和方法重复时,越往前优先级越高

9、多态

        多态是指同一个事件发生在不同的对象上会产生不同的结果,或者一个对象可以有多种形态。它是一种机制、一种能力,在类的继承中得以实现,在类的方法调用中得以体现。多态的存在可以消除类型之间的耦合关系,通过分离做什么和怎么做,将接口和实现分离开来。

        多态可以分为引用多态和方法多态。引用多态是指同一个对象变量可以指向多种实际类型的现象,而方法多态是指同一个方法可以被不同的对象调用产生不同的效果。

        多态是面向对象编程中非常重要的概念,它可以帮助我们编写更加灵活、可扩展和维护性更高的代码。

案例:

class Animal(object):
def play(self):
pass
class Tiger(Animal):
def play(self):
print("正在表演老虎吃人")
class Lion(Animal):
def play(self):
print("正在表演狮子跳火圈")
class Person(object):
def show(self, a: Animal):
print("动物开始表演了")
a.play()
p = Person()
tiger = Tiger()
lion = Lion()
# 让老虎表演
p.show(tiger)
# 让狮子表演
p.show(lion)

相关文章:

【python】面向对象(类型定义魔法方法)

目录 一、引言 二、类型定义 1、什么是类型的定义&#xff1f; 2、案例 三、魔法方法 1、什么是魔法方法 2、基础部分 3、比较操作 4、容器类型 5、属性管理 6、封装 7、方法拓展 8、继承 9、多态 一、引言 Python是一种面向对象的语言&#xff0c;它支持类&#…...

1.微服务与SpringCloud

微服务和SpringCloud 文章目录 微服务和SpringCloud1.什么是微服务2.SpringCloud3. 微服务 VS SpringCloud4. SpringCloud 组件5.参考文档6.版本要求 1.什么是微服务 微服务是将一个大型的、单一的应用程序拆分成多个小型服务&#xff0c;每个服务实现特定的业务功能&#xff…...

【2023全网最全最火】Selenium WebDriver教程(建议收藏)

在本教程中&#xff0c;我将向您介绍 Selenium Webdriver&#xff0c;它是当今市场上使用最广泛的自动化测试框架。它是开源的&#xff0c;可与所有著名的编程语言&#xff08;如Java、Python、C&#xff03;、Ruby、Perl等&#xff09;一起使用&#xff0c;以实现浏览器活动的…...

dimp 导入dmp文件报错:无效的模式名(DM8:达梦数据库)

dimp 导入dmp文件报错:无效的模式名-DM8:达梦数据库 环境介绍1 搭建A1 数据库52361.1 A1数据库5236创建模式名,表,测试数据1.2 从A1数据库5236导出dmp文件 2 搭建A2数据库52372.1 创建 数据用户ABC2311152.2 在A2 数据库5237 导入DMP(报错无效的模式名)2.3 使用REMAP_SCHEMAABC…...

宿主机无法连接docker里的redis问题解决(生产环境慎用)

宿主机无法连接docker里的redis问题解决&#xff08;生产环境慎用&#xff09; 问题描述解决方案 问题描述 1.连接超时 2.连接能连上但马上断开并报错 3.提示保护模式什么的 (error) DENIED Redis is running in protected mode because protected mode is enabled链接redis …...

给女朋友开发个小程序低价点外卖吃还能赚钱

前言 今天又是无聊的一天,逛了下GitHub,发现一个库里面介绍美团饿了吗外卖红包外卖优惠券,先领红包再下单。外卖红包优惠券,cps分成,别人领红包下单,你拿佣金。哇靠,那我岂不是可以省钱还可以赚钱,yyds。。。。想想都美好哈哈哈!!! 回到正题,这个是美团饿了么分销…...

外贸客户管理系统是什么?推荐的管理软件?

外贸客户管理系统哪个好用&#xff1f;海洋建站如何选管理系统&#xff1f; 外贸客户管理系统&#xff0c;是一款专为外贸企业设计的客户关系管理系统&#xff0c;旨在帮助外贸企业建立与维护客户关系&#xff0c;提高客户满意度和忠诚度&#xff0c;提升企业业绩。海洋建站将…...

数据挖掘:分类,聚类,关联关系,回归

数据挖掘&#xff1a; 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c;尤其sql要学&…...

力扣labuladong一刷day10一网打尽股票买卖问题共6题

力扣labuladong一刷day10股票买卖问题共6题 一、121. 买卖股票的最佳时机 题目链接&#xff1a;https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/ 思路&#xff1a;只能买入1次&#xff0c;定义dp[i][0]数组表示第i天持有股票时手中的最大金额 数&#xff0c;…...

微信小程序手写table表格

wxml <view class"table"><view class"tr bg-w"><view class"th">张三</view><view class"th" style"color: #409eff;">李四</view><view class"th ">王五</view&…...

UE5 - UI Material Lab 学习笔记

1、学习资料收集 UI Material Lab : https://www.unrealengine.com/marketplace/zh-CN/product/ui-material-lab 视频1&#xff1a;https://www.bilibili.com/video/BV1Hm4y1t7Kn/?spm_id_from333.337.search-card.all.click&vd_source707ec8983cc32e6e065d5496a7f79ee6 视…...

oracle删除重复的数据

去除重复数据&#xff1a; group by 对要比对的字段进行查询是否重复 CREATE TABLE 临时表 AS (select 字段1,字段2,count(*) from 表名 group by 字段1,字段2 having count(*) > 1) 上面这句话就是建立了临时表&#xff0c;并将查询到的数据插入其中。 下面就可以进行…...

Python中的并发编程是什么,如何使用Python进行并发编程?

Python中的并发编程是指使用多线程或多进程来同时执行多个任务。这样可以提高程序的执行效率&#xff0c;特别是在处理I/O密集型任务时。Python提供了多种方式来实现并发编程&#xff0c;如threading模块和multiprocessing模块。 使用Python进行并发编程的方法如下&#xff1a…...

【LeetCode】136. 只出现一次的数字

136. 只出现一次的数字 难度&#xff1a;简单 题目 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且该算法只使用…...

HTTP服务器——tomcat的安装和使用

文章目录 前言下载tomcattomcat 文件bin 文件夹conf 文件lib 文件log 文件temp 文件webapps 文件work 目录 如何使用 tomcat 前言 前面我们已经学习了应用层协议 HTTP 协议和 HTTP 的改进版——HTTPS&#xff0c;这些协议是我们在写与服务器相关的代码的时候息息相关的&#x…...

代码随想录Day45 动态规划13 LeetCode T1143最长公共子序列 T1135 不相交的线 T53最大子数组和

LeetCode T1143 最长公共子序列 题目链接:1143. 最长公共子序列 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 动规五部曲分析 1.确定dp数组的含义 这里dp数组的含义是结尾分别为i-1,j-1的text1和text2的最长公共子序列长度 至于为什么是i-1,j-1我之前已经说过了,这里再…...

写了个监控 ElasticSearch 进程异常的脚本!

服务器配置免密钥环境准备&#xff1a; 配置免密钥前&#xff0c;需要在服务器的 hosts 文件中配置目标主机名称与 IP 对应关系。 vim /etc/hosts IP1 hostname1 IP2 hostname2 ...... 将 mianmiyaojiaoben.zip 安装包解压在当前目录下 cd /usr/local/jiaoben unzip mianmi…...

第三篇 基于JSP 技术的网上购书系统—— 数据库系统设计(网上商城、仿淘宝、当当、亚马逊)

目录 1.逻辑关系设计 2.物理设计 2.1管理员表 2.2留言表 2.3会员登录表 2.4会员表 2.5订单表 2.6订单商品表 2.7产品表 2.8产品货架表 2.9收藏表 2.10类别表 2.11新闻表 数据库系统是用来保存数据的软件系统&#xff0c;当今比较流行的数据库系统&#xff0c;如 MS…...

电脑检测温度软件有哪些?

环境&#xff1a; Win10 专业版 问题描述&#xff1a; 电脑检测温度软件有哪些&#xff1f; 解决方案&#xff1a; 有很多电脑检测温度的软件可供选择&#xff0c;以下是一些常用的电脑温度监测工具&#xff1a; HWMonitor&#xff1a;一款免费的硬件监控软件&#xff0…...

设计模式 -- 单例模式(Singleton Pattern)

单例模式&#xff1a;最简单的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式…...

ubuntu给终端加代理服务器

ubuntu给终端加代理 访问google.com 是否可以访问通 curl https://www.google.com如果访问不通说明代理服务器没有配置好。 使用 gedit ~/.bashrc 打开网络配置 gedit ~/.bashrc找到文章的最后添加代理 export http_proxyhttp://127.0.0.1:7890 export https_proxyhttp://…...

centos 6.10 安装 readline 6.2.0

下载地址 解压文件 cd readline-6.2 ./configure -prefix /usr/local/readline-6.2 make && make install安装完成...

IDEA 2023搭建 SpringMVC +FreeMarker+JDBC

1.IDEA的版本&#xff0c;目前最新是2023&#xff0c;要选择旗舰版。笔者曾选择社区版&#xff0c;发现少了很多功能。只能重新安装。 2.安装好以后的第1件事&#xff0c;是设置Maven&#xff0c;并将下载地址改为淘定站&#xff0c;参照这篇一次包会——最新IDEA配置Maven指南…...

RabbitMQ传统数据持久化和Lazy queue的区别

问题引出&#xff1a; 在了解这个问题前我们需要一些前置知识&#xff1a; 关于MQ可靠性&#xff0c;在默认情况下&#xff0c;RabbitMQ会将接收到的信息保存在内存中以降低消息收发的延迟。这样会导致两个问题&#xff1a; 一旦MQ宕机&#xff0c;内存中的信息会丢失 内存空…...

docker部署lnmp环境

文章目录 前期准备&#xff1a;一、部署mysql1.1 获取 Mysql 5.7.22 镜像1.2 启动mysql容器 二、部署php2.1 获取php 7.2镜像2.2 启动php 容器2.3 php的扩展安装 三、部署nginx3.1 获取nginx:1.14镜像3.2 启动nginx容器3.3 编写nginx虚拟主机配置文件&#xff0c;使其支持php3.…...

数据结构 | 带头双向循环链表专题

数据结构 | 带头双向循环链表专题 前言 前面我们学了单链表&#xff0c;我们这次来看一个专题带头的双向循环链表~~ 文章目录 数据结构 | 带头双向循环链表专题前言带头双向循环链表的结构实现双向链表头文件的定义创建节点哨兵位初始化尾插尾删头插头删打印查找指定位置前插入…...

Redis使用Pipeline(管道)批量处理

Redis 批量处理 在开发中&#xff0c;有时需要对Redis 进行大批量的处理。 比如Redis批量查询多个Hash。如果是在for循环中逐个查询&#xff0c;那性能会很差。 这时&#xff0c;可以使用 Pipeline (管道)。 Pipeline (管道) Pipeline (管道) 可以一次性发送多条命令并在执…...

Linux中at命令添加一次性任务

1、工作原理 功能&#xff1a;在某个时间点&#xff0c;执行一次命令。 特点&#xff1a;任务是用户隔离的。 条件&#xff1a;必须要保证atd进程存在。 ps -ef |grep atd 原理&#xff1a;atd进程循环遍历队列里的任务&#xff0c;有任务&#xff0c;且到达执行时间&#xff…...

交换机基础知识之安全配置

交换机在网络基础设施中扮演着重要角色&#xff0c;它促进了设备之间数据包的流动。正因此&#xff0c;采取适当的安全措施来保护网络免受未经授权的访问和潜在攻击至关重要。本文将全面解读交换机基础安全配置知识&#xff0c;并提供实践方案&#xff0c;以保证安全的网络环境…...

Netty入门指南之Reactor模型

作者简介&#xff1a;☕️大家好&#xff0c;我是Aomsir&#xff0c;一个爱折腾的开发者&#xff01; 个人主页&#xff1a;Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客 当前专栏&#xff1a;Netty应用专栏_Aomsir的博客-CSDN博客 文章目录 参考文献前言单线程…...