百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

第8天 | 12天搞定Python,面向对象

off999 2024-09-23 11:31 31 浏览 0 评论

国内有一档很火的相亲节目,不知你看过没?相亲环节大概是这样的:台上站着一排美女,每个美女面前都有一个唯一编号(如NO.1)。一男的从电梯里出来,然后面向1至11号美女对象,面向对象。然后男的经过一番秀(背景秀、才艺秀、印象秀等)之后,美女用按灯的方法,决定男的去留。

不知你注意到没,相亲的人,是同一类人,都是未婚的人,都是光棍,都是单身狗。

在面向对象编程语言(C++、Java、C#、Python等)中,就是把相同性质(都是单身狗)的事物归成一类,再从类中实例化到那个对象(如:1号美女),美其名曰面向对象编程。

面向对象,让零散的函数成为整体,它将现实世界的事物抽象成对象,描叙其在整个解决问题的步骤中的行为,贴近现实生活中对事物的描述,更有利于人们对复杂系统进行分析、设计和编程。

8.1 类和对象

面向对象中,类和对象是两个非常重要的角色。类是对具有相同特性和行为的对象的抽象,如单身狗。在Python语言中,类使用class关键字+类名+冒号:结尾的方式创建。类名用大写字母开头。类的实例化(具体化)就是对象,如1号美女。

# 定义单身狗类
class SingleDog:

    def __init__(self, num):
        self.num = num

    # 按下灯
    def push(self):
        print("%d号美女灭灯" % self.num)
        return True


# 对象1:1号美女
singleDog = SingleDog(1)
singleDog.push()
# 对象2:2号美女
singleDog = SingleDog(2)
singleDog.push()

输出结果

1号美女灭灯
2号美女灭灯

不知你明白了,单身狗程序员。

8.2 实例方法

在类里,定义方法时,如果第一个参数是self,表示这个方法为实例方法。实例方法,只能通过对象和.的方式进行调用。

以__init__命名的方法,是类的构造方法,它有且只能有一个,默认为:__init__()。

有构造就有析构,析构方法是以__del__命名的。默认为:__del__(),它经常用来释放资源,如断开数据库连接。

# 定义一个类
class Product:
    # 产品编号
    num = 168168

# 构造方法
    def __init__(self):
        print("创建时调用")

    # 实例方法
    def get_num(self):
        return self.num

    # 析构方法
    def __del__(self):
        print("销毁时调用")


# 实例化并调用方法
p = Product()
print(p.get_num())

输出结果

创建时调用
168168
销毁时调用

8.3 静态方法

静态方法,通过类名和.直接调用,不需要创建对象。方法里,不用self参数。用@staticmethod装饰器声明。当然,用实例对象也是可以调用的。

# 定义一个订单类
class Order:

    # 静态方法
    @staticmethod
    def get_title():
        return "好大一个单"


# 实例化并调用方法
order = Order()
print(order.get_title())
# 直接用类名调用
print(Order.get_title())

输出结果

好大一个单
好大一个单

8.4 类方法

类方法,在Python中使用较少,类方法传入的第一个参数为cls,是类本身。类方法可以通过类名或实例名调用。类方法@classmethod装饰器和cls参数声明。

# 定义一个客户类
class Customer:

    # 类方法
    @classmethod
    def get_name(cls):
        return "西门吹水"


# 实例化并调用方法
c = Customer()
print(c.get_name())
# 直接用类名调用
print(Customer.get_name())

输出结果

西门吹水
西门吹水

8.5 方法总结

实例方法第一个参数永远是self,类方法第一个参数永远是 cls,而静态方法没有任何必选参数。

静态方法不会访问到class 本身 ,它只是一个函数,没有访问对象和它的内部(属性和其他方法),而实例方法会访问self,类方法会访问 cls。

实例方法只能被实例对象访问。而静态方法、类方法既可被类访问,也可以被实例对象访问。

# 类里的各种方法
class Employee:

    # 构造方法
    def __init__(self, name, address):
        self.name = name
        self.address = address

    # 实例方法
    def get_address(self):
        return self.address

    # 静态方法
    @staticmethod
    def get_name():
        return "西门吹水"

    # 类方法
    @classmethod
    def get_age(cls):
        return 38


# 析构方法
def __del__(self):
    print("释放资源")


# 实例化
c = Employee("程序员", "今日头条:老陈说编程")
# 静态方法
print(Employee.get_name())
# 实力方法
print(c.get_address())
# 直接用类名调用
print(Employee.get_age())

输出方法

西门吹水
今日头条:老陈说编程
38

8.6 数据封装

数据封装是面向对象编程的一个重要特点,它通过限制访问,对数据进行保护。封装,即是在类内部,将某些不想被外部访问或调用的部分内容隐藏起来,如若外部要调用,只能通过公开的接口进行。Python语言没有private、protected这些关键字, 它用双下划线__表示私有类型(private)的属性或方法。以单下划线_开头的表示的是protected 类型的属性和方法。

# 定义一个员工类
class Employee:

    # 私有属性
    __age = 18
    # 私有属性
    __address = "广东"
    # 公有属性
    phone = 12345678910

    def __init__(self, name):
        self.name = name

    # 公有方法
    def get_age(self):
        return self.__age

    # 公有方法
    def get_name(self):
        return self.name

    # 私有方法
    def __get_address(self):
        return self.__address


e = Employee("王二麻子")
print(e.phone)
print(e.get_name())
print(e.get_age())
# 私有属性和方法不可调用
# print(e.__age())
# print(e.__get_address())

其实Python并没有真正的私有属性或方法,通过对象._类名__私有属性名或对象._类名__私有方法名,就可以访问私有属性或私有方法。

# 定义一个员工类
class Employee:
    # 私有属性
    __name = "酷哥"

    # 私有方法
    def __get_age(self):
        return 18


e = Employee()
# 私有属性或方法都可以访问
print(e._Employee__name)
print(e._Employee__get_age())

输出结果

酷哥
18

8.7 None值

Python语言中没有NULL值,有None值。Nono不是空,也不是0。它也是一种数据类型NoneType。判断一个对象是否为None值,可通过is进行。

# None值
n = None
print(n)
print(type(n))
if n is None:
    print("对象不存在")
else:
    print("对象存在")

# --not is 为反过来的判断—
if n is not None:
    print("对象存在")
else:
    print("对象不存在")

输出结果

None
<class 'NoneType'>
对象不存在
对象不存在

8.8 继承

即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

class ClassName(基类):

# 类定义
class People:
    # 定义基本属性
    name = ''
    age = 0
    # 私有属性,体重(公斤)
    __weight = 0

    # 定义构造方法
    def __init__(self, n, a, w):
        self.name = n
        self.age = a
        self.__weight = w

    def speak(self):
        print("%s说:我%d岁。" % (self.name, self.age))


# 单继承示例
class Teacher(People):
    grade = ''

    def __init__(self, n, a, w, g):
        # 调用父类的构函
        People.__init__(self, n, a, w)
        self.grade = g

    # 覆写父类的方法
    def speak(self):
        print("%s说: 我%d岁了,我在教%d年级" % (self.name, self.age, self.grade))


s = Teacher('marry', 30, 65, 6)
s.speak()

输出结果

marry说: 我30岁了,我在教6年级

请注意,请注意,Python可支持多继承,语法是:class ClassName(基类1, 基类2, 基类3):

8.9 方法重写

如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法。可用super() 函数调用父类(超类)的方法。

# 定义父类
class Parent:
    def m(self):
        print('调用父类方法')


class Child(Parent):  # 定义子类
    def m(self):
        print('调用子类方法')


c = Child()  # 子类实例
c.m()  # 子类调用重写方法
super(Child, c).m()

输出结果

调用子类方法
调用父类方法

8.10 对象判断

判断两个标识符是否引用同一个对象时,可以用is进行比较,还可以用相反的方式,is not进行比较。is 跟 == 的区别是:is用于判断两个变量是否引用同一个对象,==是比较两个变量的值是否相等。可通过id()函数获得对象引用地址。

# 定义父类
class Parent:
    def m(self):
        print('调用父类方法')


class Child(Parent):  # 定义子类
    def m(self):
        print('调用子类方法')


p = Parent()
c = Child()     # 子类实例
print(c is p)
# 数组
a = (5, 6, 8)
b = a
print(id(a), id(b))
print(a is b)
print(a, "==", b)
print(a == b)

输出结果

False
140317976246976 140317976246976
True
(5, 6, 8) == (5, 6, 8)
True

好了,有关面向对象的内容,老陈讲完了,如果觉得对你有所帮助,希望老铁能转发点赞,让更多的人看到这篇文章。你的转发和点赞,就是对老陈继续创作和分享最大的鼓励。

一个当了10年技术总监的老家伙,分享多年的编程经验。想学编程的朋友,可关注今日头条:老陈说编程。我将分享Python,前端(小程序)和App方面的编程知识。关注我,没错的。

8.11 枚举类型

枚举语法跟类差不多,放在一起学习效果更好。 枚举(Enum)跟整型一样,是一种数据类型。它是一系列常量的集合,通常用于表示某些特定的有限集合,如月份、星期、状态、性别(男、女、不男不女)等,当一个变量有几种可能取值的时候,定义为枚举类型。

1. 枚举定义

枚举是不可变类型,一旦定义创建,其成员的值不可改变,名称不可重复,通过class关键字和继承Enum类进行定义。定义时若出现成员的值相同,那只有第一个有效,其语法结构为:

class 枚举名(Enum):

成员名1 = 值1

成员名x = 值n

# ---引入枚举类---
from enum import Enum


class Colors(Enum):
    red = 1
    orange = 2
    yellow = 3
    green = 4
    red_alias = 1


print(Colors(1))

输出结果

Colors.red

2. 整型枚举

枚举成员的值支持多种数据类型,如字符串、布尔或整型等,如要指定为整型,可继承IntEnum类。注意,就算指定为IntEnum,其成员的值照样可以为字符串等,但在获取成员的值时,会进行自动转换,如果转换失败,会报错。当然,既然指定为整型了,就不要故意指定为字符串等了。

# ---引入枚举类---
from enum import Enum, IntEnum


# 字符串枚举
class Gender(Enum):
    Male = "男"
    Female = "女"
    Unknown = "保密"
    

print(Gender.Male.value)


# 整型枚举
class Number(IntEnum):
    One = 1
    Two = 2
    # 会自动转为整型
    Three = "3"


print(Number.Three.value)

输出结果

男
3

3. 唯一值

如果要限制定义枚举时,不能定义相同值的成员。可以使用装饰器@unique进行限制。如若出现相同值,运行时会报错。

# 引入枚举类和唯一装饰器
from enum import Enum, unique


@unique
class Weekday(Enum):

    Sun = 0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6


print(Weekday.Sat.value)

输出结果

6

4. 枚举取值

枚举可通过成员获取它的名称和值,可通过名称或值获取成员。

# 引入枚举类和唯一装饰器
from enum import Enum, unique


@unique
class Months(Enum):
    Jan = 1
    Feb = 2
    Mar = 3
    Apr = 4
    May = 5
    Jun = 6
    Jul = 7
    Aug = 8
    Sep = 9
    Oct = 10
    Nov = 11
    Dec = 12

# 通过成员获取名称和值
print(Months.Jan.name, Months.Jan.value)
# 通过名称和值获取成员
print(Months["Feb"], Months(2))

输出结果

Jan 1
Months.Feb Months.Feb

5. 枚举遍历

通过for循环遍历枚举成员时,如若出现成员的值相同时,只获取第一个成员。当然,如果要遍历所有成员的话,得用特殊的方式获取,就是通过__menbers__属性。

# ---引入枚举类---
from enum import Enum


class Colors(Enum):
    red = 1
    orange = 2
    yellow = 3
    green = 4
    red_alias = 1


# 获取成员名称,值相等的,只获取第一个
for color in Colors:
    print(color.name)

# 获取所有成员名称
for color in Colors.__members__:
    print(color)

输出结果

red
orange
yellow
green
red
orange
yellow
green
red_alias

6. 枚举比较

枚举成员不可以比较大小,但可以通过is、is not 和==、!=进行同性或等值比较。

# ---引入枚举类---
from enum import Enum


class Colors(Enum):
    red = 1
    orange = 2
    yellow = 3
    green = 4
    red_alias = 1


# is 判断
result = Colors.red is Colors.red
print(result)
# is not判断
result = Colors.red is not Colors.green
print(result)
# ==比较值是否相等
result = Colors.red == Colors.red_alias
print(result)
# !=比较值是否不相等
result = Colors.red != Colors.green
print(result)

输出结果

True
True
True
True

7. 类中枚举

枚举可以定义在类里,并可通过类名和枚举名进行调用。

# ---引入枚举类---
from enum import Enum


class Plane:

    def __init__(self, color):
        self.color = color

    # 类的成员
    class Colors(Enum):
        Red = 1
        Orange = 2
        Yellow = 3
        Green = 4
        Blue = 5


plane = Plane(Plane.Colors.Blue.value)
print(plane.color)

输出结果

5

好了,有关枚举类型的内容,老陈讲完了,如果觉得对你有所帮助,希望老铁能转发点赞,让更多的人看到这篇文章。你的转发和点赞,就是对老陈继续创作和分享最大的鼓励。

一个当了10年技术总监的老家伙,分享多年的编程经验。想学编程的朋友,可关注今日头条:老陈说编程。我将分享Python,前端(小程序)和App方面的编程知识。关注我,没错的。

#Python##Python编程从入门到实践##程序员#

相关推荐

apisix动态修改路由的原理_动态路由协议rip的配置

ApacheAPISIX能够实现动态修改路由(DynamicRouting)的核心原理,是它将传统的静态Nginx配置彻底解耦,通过中心化配置存储(如etcd)+OpenRest...

使用 Docker 部署 OpenResty Manager 搭建可视化反向代理系统

在之前的文章中,xiaoz推荐过可视化Nginx反向代理工具NginxProxyManager,最近xiaoz还发现一款功能更加强大,界面更加漂亮的OpenRestyManager,完全可以替代...

OpenResty 入门指南:从基础到动态路由实战

一、引言1.1OpenResty简介OpenResty是一款基于Nginx的高性能Web平台,通过集成Lua脚本和丰富的模块,将Nginx从静态反向代理转变为可动态编程的应用平台...

OpenResty 的 Lua 动态能力_openresty 动态upstream

OpenResty的Lua动态能力是其最核心的优势,它将LuaJIT嵌入到Nginx的每一个请求处理阶段,使得开发者可以用Lua脚本动态控制请求的生命周期,而无需重新编译或rel...

LVS和Nginx_lvs和nginx的区别

LVS(LinuxVirtualServer)和Nginx都是常用的负载均衡解决方案,广泛应用于大型网站和分布式系统中,以提高系统的性能、可用性和可扩展性。一、基本概念1.LVS(Linux...

外网连接到内网服务器需要端口映射吗,如何操作?

外网访问内网服务器通常需要端口映射(或内网穿透),这是跨越公网与私网边界的关键技术。操作方式取决于网络环境,以下分场景详解。一、端口映射的核心原理内网服务器位于私有IP地址段(如192.168.x.x...

Nginx如何解决C10K问题(1万个并发连接)?

关注△mikechen△,十余年BAT架构经验倾囊相授!大家好,我是mikechen。Nginx是大型架构的必备中间件,下面我就全面来详解NginxC10k问题@mikechen文章来源:mikec...

炸场!Spring Boot 9 大内置过滤器实战手册:从坑到神

炸场!SpringBoot9大内置过滤器实战手册:从坑到神在Java开发圈摸爬滚打十年,见过太多团队重复造轮子——明明SpringBoot自带的过滤器就能解决的问题,偏偏要手写几十...

WordPress和Typecho xmlrpc漏洞_wordpress主题漏洞

一般大家都关注WordPress,毕竟用户量巨大,而国内的Typecho作为轻量级的博客系统就关注的人并不多。Typecho有很多借鉴WordPress的,包括兼容的xmlrpc接口,而WordPre...

Linux Shell 入门教程(六):重定向、管道与命令替换

在前几篇中,我们学习了函数、流程控制等Shell编程的基础内容。现在我们来探索更高级的功能:如何控制数据流向、将命令链接在一起、让命令间通信变得可能。一、输入输出重定向(>、>>...

Nginx的location匹配规则,90%的人都没完全搞懂,一张图让你秒懂

刚配完nginx网站就崩了?运维和开发都头疼的location匹配规则优先级,弄错顺序直接导致500错误。核心在于nginx处理location时顺序严格:先精确匹配=,然后前缀匹配^~,接着按顺序正...

liunx服务器查看故障命令有那些?_linux查看服务器性能命令

在Linux服务器上排查故障时,需要使用一系列命令来检查系统状态、日志文件、资源利用情况以及网络状况。以下是常用的故障排查命令,按照不同场景分类说明。1.系统资源相关命令1.1查看CPU使...

服务器被入侵的常见迹象有哪些?_服务器入侵可以被完全操纵吗

服务器被入侵可能会导致数据泄露、服务异常或完全失控。及时发现入侵迹象能够帮助你尽早采取措施,减少损失。以下是服务器被入侵的常见迹象以及相关的分析与处理建议。1.服务器被入侵的常见迹象1.1系统性能...

前端错误可观测最佳实践_前端错误提示

场景解析对于前端项目,生产环境的代码通常经过压缩、混淆和打包处理,当代码在运行过程中产生错误时,通常难以还原原始代码从而定位问题,对于深度混淆尤其如此,因此Mozilla自2011年开始发起并...

8个能让你的Kubernetes集群“瞬间崩溃”的配置错误

错误一:livenessProbe探针“自杀式”配置——30秒内让Pod重启20次现象:Pod状态在Running→Terminating→CrashLoopBackOff之间循环,重启间隔仅...

取消回复欢迎 发表评论: