Python类与面向对象

一、面向对象

1.1 面向对象概述

面向对象与面向过程?

面向过程编程的基本思想是:分析解决问题的步骤,使用函数实现每步对应的功能,按照步骤的先后顺序依次调用函数。面向过程只考虑如何解决当前问题,它着眼于问题本身。

面向对象编程的基本思想是:着眼于角色以及角色之间的联系。使用面向对象编程思想解决问题时,开发人员首先会从问题之中提炼出问题涉及的角色,将不同角色各自的特征和关系进行封装,以角色为主体,为不同角度定义不同的属性和方法,以描述角色各自的属性与行为。

1.2 面向对象的基本概念

1.对象

对象是一个程序模块,从用户来看,对象为他们提供所希望的行为。对象既可以是具体的物理实体的事物,也可以是人为的概念,如一名员工、一家公司、一辆汽车、一个故事等。

2.类

在面向对象的方法中,类是具有相同属性行为的一组对象的集合,它提供了一个抽象的描述,其内部包括属性和方法两个主要部分。

3.抽象

抽象是抽取特定实例的共同特征,形成概念的过程。抽象主要是为了使复杂度降低,它强调主要特征,忽略次要特征,以得到较简单的概念,从而让人们能控制其过程或以综合的角度来了解许多特定的事态。

4.封装

封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,避免了外界直接访问对象属性而造成耦合度过高及过度依赖,同时也阻止了外界对对象内部数据的修改而可能引发的不可预知错误。

5.继承

继承不仅增强了代码复用性,提高了开发效率,也为程序的扩充提供了便利。在软件开发中,类的继承性使所建立的软件具有开放性、可扩充性,这是数据组织和分类行之有效的方法,它降低了创建对象、类的工作量。

6.多态

多态指同一属性或行为在父类及其各派生类中具有不同的语义,面向对象的多态特性使开发更科学、更符合人类的思维习惯,能有效地提高软件开发效率,缩短开发周期,提高软件的可靠性。

二、类与对象

2.1 类与对象的关系

类是对多个对象共同特征的抽象描述,是对象的模板;对象用于描述现实中的个体,它是类的实例。

2.2 类的定义与访问

类的定义格式如下:

class 类名:  # 使用class定义类 类名首字母一般为大写
属性名 = 属性值 # 定义属性
def 方法名(self,形参1,形参2,...,形参N): # 定义方法 方法中有一个指向对象的默认参数self
方法体

可以看到,在方法定义的参数中,有一个:self关键字。self关键字是成员方法定义的时候,必须填写的

  • 它用来表示类对象本身的意思
  • 当我们使用类对象调用方法的时候,self会自动被python传入
  • 在方法内部,想要访问类的成员变量,必须使用self
  • self关键字,尽管在参数列表中,但是传参的时候可以忽略它。

2.3 对象的创建与使用

类定义完成后不能直接使用,程序中的类需要实例化为对象才能实现其意义。

对象的创建格式

对象名=类名()

访问对象成员

对象名.属性    # 访问对象属性
对象名.方法() # 访问对象方法

2.4 访问控制

类中定义的属性和方法默认为公有属性和方法,该类的对象可以任意访问类的公有成员。为了契合封装原则,python支持将类中的成员设置为私有成员,在一定程度上限制对象对类成员的访问。

定义私有成员

python通过在类成员名之前添加双下画线(__)来限制成员的访问权限,语法格式如下:

__属性名
__方法名
class PersonInfo:
__weight = 55 # 私有属性
def __info(self): # 私有方法
print(f"我的体重是:{__weight}")

私有成员的访问

对象无法直接访问类的私有成员。下面演示如何在类内部访问私有属性和私有方法。

访问私有属性。私有属性可在公有方法中通过指代类本身的默认参数self访问,类外部可通过公有方法间接获取类的私有属性。

class PersonInfo:
__weight = 65 # 私有属性 def get_weight(self):
print(f'体重:{self.__weight}kg') # 体重:65kg
personInfo = PersonInfo()
personInfo.get_weight()

访问私有方法。私有方法同样在公有方法中通过参数self访问。

class PersonInfo:
__weight = 65 # 私有属性 def __info(self): # 私有方法
print(f"我的体重是:{self.__weight}") def get_weight(self):
print(f'体重:{self.__weight}kg')
self.__info() # 创建PersonInfo类的对象person,访问公有方法get_weight()
personInfo = PersonInfo() # 体重:65kg
personInfo.get_weight() # 我的体重是:65

三、构造方法与析构方法

类中有两个特殊的方法:构造方法_init_()和析构方法__del()__。这两个方法分别在类创建和销毁的时候自动调用。

3.1 构造方法

每个类都有一个默认的_init_()方法,如果在定义类时显示地定义了_init()方法,则创建对象时python解释器会调用显式定义的_init_()方法;如果定义类时没有显式定义_init()方法,那么Python解释器会调用默认的_init()方法。

class Information(object):
def __init__(self, name, sex): # 有参构造方法
self.name = name # 添加属性name
self.sex = sex # 添加属性sex def info(self):
print(f'姓名:{self.name}') # 姓名:齐纳
print(f'性别:{self.sex}') # 性别:男 information = Information('齐纳', '男')
information.info()

注意:前面在类中定义的属性是类属性,可以通过对象或类进行访问;在构造方法中定义的属性是实例属性,只能通过对象进行访问。

3.2 析构方法

在创建对象时,系统会自动调用_init_()方法,在对象被清理时,系统也会自动调用一个_del_()方法,这个方法就是类的析构方法。

扩展:python的垃圾回收机制。Pyhton中的垃圾回收主要采用的是引用计数。引用计数是一种内存管理技术,他通过引用计数器记录所有对象的引用数量,当对象的引用计数器数值为0时,就会将该对象视为垃圾进行回收。

import sys
# getrefcount()函数是sys模块中用于统计对象引用数量的函数,其返回结果通常比预期结果大1,这是因为getrefcount()函数也会统计临时对象的引用 class Destruction:
def __init__(self):
print('对象被创建') def __del__(self):
print('对象被销毁')
# 调用getrefcount()函数返回Destruction类的对象的引用计数器的值。
destruction = Destruction()
print(sys.getrefcount(destruction)) # 2

3.3 其他方法

_str_()

# __str__字符串方法
class Student:
def __init__(self, name, age):
self.name = name
self.age = age def __str__(self):
return f'Student类对象,name={self.name},age={self.age}'
student = Student("赵无极", 10)
# print(student) # <__main__.Student object at 0x0000017F57579390>
# print(str(student)) # <__main__.Student object at 0x0000017F57579390>
print(student) # Student类对象,name=赵无极,age=10
print(str(student)) # Student类对象,name=赵无极,age=10
# 当类对象需要被转换为字符串之时,会输出如上结果(内存地址)
# 我们可以通过__str__方法,控制类转换为字符串的行为。

_lt_ 小于符号比较方法

class Student:
def __init__(self, name, age):
self.name = name
self.age = age def __lt__(self, other):
return self.age < other.age
stu1 = Student("周杰伦", 41)
stu2 = Student("林俊杰", 42)
# 直接对2个对象进行比较是不可以的,但是在类中实现__lt__方法,即可同时完成:小于符号 和 大于符号 2种比较
print(stu1 < stu2) # True
print(stu1 > stu2) # False

_le_ 小于等于比较符号方法

__le__可用于:<=、>=两种比较运算符上。

class Student:
def __init__(self, name, age):
self.name = name
self.age = age def __le__(self, other):
return self.age < other.age
stu1 = Student("周杰伦", 41)
stu2 = Student("林俊杰", 41)
print(stu1 <= stu2) # True
print(stu1 >= stu2) # False

_eq_,比较运算符实现方法

不实现__eq__方法,对象之间可以比较,但是是比较内存地址,也即是:不同对象==比较一定是False结果。实现了__eq__方法,就可以按照自己的想法来决定2个对象是否相等了。

class Student:
def __init__(self, name, age):
self.name = name
self.age = age def __eq__(self, other):
return self.age == other.age student1 = Student("周杰库", 41)
student2 = Student("张学友", 41)
print(student2 == student1) # True

3.4 总结

四、类方法和静态方法

4.1 类方法

扩展:实例方法:直接定义、只比普通函数多一个self参数的方法是类最基本的方法,这种方法称为实例方法,它只能通过类实例化的对象调用。

类方法与实例方法有以下不同:

  • 类方法使用装饰器@classmethod修饰
  • 类方法的第一个参数是cls而非self,它代表类本身
  • 类方法即可由对象调用,也可直接由类来调用
  • 类方法可以修改类属性,实例方法无法修改类属性

定义类方法

语法格式如下:

类名.类方法
对象名.类方法
class Test:
@classmethod
def use_class_method(cls):
print(f'我是类方法') test = Test()
Test.use_class_method() # 类名调用方法
test.use_class_method() # 对象名调用方法

从输出结果可以看出,使用类名或对象名均可调用类方法。

4.2 修改类属性

在实例方法中无法修改类属性的值,但在类方法中可以修改类属性的值。

class Apple(object):  # 定义Apple类
count = 0 # 定义类属性 def add_one(self):
self.count = 1 # 对象方法 @classmethod
def add_two(cls):
cls.count = 2 # 类方法 apple = Apple()
apple.add_one()
print(Apple.count) # 0
print(apple.count) # 1
Apple.add_two()
print(Apple.count) # 2

从输出结果可以看出,调用实例方法add_one()后访问count的值为0,说明count的值没有被修改;调用类方法add_two()后再次访问count的值为2,说明类属性count的值被修改成功。

思考:通过"self.count=1"只是创建了一个与类属性同名的实例属性count并将其赋值为1,而非对类属性进行重新赋值。

4.3 静态方法

静态方法与实例方法有以下不同:

  • 静态方法没有self参数,它需要使用@staticmethod修饰
  • 静态方法中需要以“类名.方法名/属性名”的形式访问类的成员
  • 静态方法即可有对象调用,亦可直接由类调用
class Example:
num = 10 # 类属性 @staticmethod # 定义静态方法
def static_method():
print(f'类属性的值为:{Example.num}')
print('--静态方法--') example = Example() # 创建对象
example.static_method() # 对象调用
Example.static_method() # 类调用

总结:类方法和静态方法的区别

类方法和静态方法最主要的区别在于类方法有一个cls参数,使用该参数可以在类方法中访问类的成员;静态方法没有任何默认参数,它无法使用默认参数访问类的成员。因此,静态方法更适合与类无关的操作。

五、继承

5.1 单继承

单继承指的是子类只继承一个父类,其语法格式如下:

class 子类(父类):
class Amphibian:
name = '两栖动物' def features(self):
print('幼年用腮呼吸')
print('成年用肺兼皮肤呼吸') class Frog(Amphibian): # Frog类继承自Amphibian类
def attr(self):
print(f'青蛙是{self.name}')
print('我会呱呱叫') frog = Frog() # 创建类的实例化对象
print(frog.name) # 访问父类的属性 两栖动物
frog.features() # 使用父类的方法 幼年用腮呼吸 成年用肺兼皮肤呼吸
frog.attr() # 使用自身的方法 青蛙是两栖动物 我会呱呱叫

从输出结果可以看出,子类继承父类之后,就拥有了父类继承的属性和方法,它既可以调用自己的方法,也可以调用从分类继承的方法。

扩展:isinstance()函数与issubclass()函数

isinstance(o,t)函数用于检查对象的类型,它有两个参数,第一个参数是要判断类型的对象(o),第二个参数是类型(t),如果o是t类型的对象,则函数返回True,否则返回False

print(isinstance(frog, Frog))   # True

函数issubclass(cls,classinfo)用于检查类的继承关系,它也有2个参数:第一个参数是要判断的子类型(cls);第二个参数是要判断的父类类型(classinfo)。如果cls类型是classinfo类型的子类,则函数返回True,否则返回False。

print(issubclass(Frog, Amphibian))   # True

5.2 多继承

多基础指的是一个子类继承多个父类,其语法格式如下:

class 子类(父类A, 父类B):
class English:
def eng_konw(self):
print('具备英语知识') class Math:
def math_koow(self):
print('具备数学知识') class Student(English, Math):
def study(self):
print('学生的任务是学习') s = Student()
s.eng_konw() # 具备英语知识
s.math_koow() # 具备数学知识
s.study() # 学生的任务是学习

注意事项:多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。

即:先继承的保留,后继承的被覆盖

5.3 方法的重写

子类可以继承父类的属性和方法,若父类的方法不能满足子类的要求,子类可以重写父类的方法,以实现辅助的功能。

class Felines:
def speciality(self):
print("猫科动物特长是爬树") class Cat(Felines):
name = "猫" def speciality(self):
print(f'{self.name}会抓老鼠')
print(f'{self.name}会爬树') cat = Cat()
cat.speciality()

程序运行结果:

猫会抓老鼠
猫会爬树

5.4 super()函数

如果子类重写了父类的方法,但仍希望调用父类中的方法,可以通过super()函数调用父类的方法。

super()函数使用方法如下:

super().方法名()
class Felines:
def speciality(self):
print("猫科动物特长是爬树") class Cat(Felines):
name = "猫" def speciality(self):
print(f'{self.name}会抓老鼠')
print(f'{self.name}会爬树')
print("*" * 20)
super().speciality() cat = Cat()
cat.speciality()

程序运行结果如下:

猫会抓老鼠
猫会爬树
********************
猫科动物特长是爬树

从输出结果可以看出,通过super()函数可以访问被重写的父类方法。

5.5 多态

在Python中,多态值在不考虑对象类型的情况下使用对象。Python中并不需要显式指定对象的类型,只要对象具有预期的方法和表达式操作符,就可以使用对象。

pass关键字的作用是什么?

pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思。

class Animal(object):  # 定义父类Animal
def move(self):
pass class Rabbit(Animal): # 定义子类Rabbit
def move(self):
print('兔子蹦蹦跳跳') class Snail(Animal): # 定义子类Snail
def move(self):
print('蜗牛缓慢爬行') def test(obj):
obj.move() rabbit = Rabbit()
test(rabbit) # 接受Rabbit对象
snail = Snail()
test(snail) # 接受Snail对象

程序运行结果

兔子蹦蹦跳跳
蜗牛缓慢爬行

从运行结果看出,同一个函数会根据参数的类型去调用不同的方法,从而产生不同的结果。

六、类型注解

7.1 变量的类型注解

Pyhton在3.5版本的时候引入了类型注解,以方便静态类型检查工具,IDE等第三方工具。

类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显示的说明)。

主要功能:

  • 帮助第三方IDE工具(如Pycharm)对代码进行类型推断,协助做代码提示
  • 帮助开发者自身对变量进行类型注释

支持:

  • 变量的类型注解
  • 函数(方法)形参列表和返回值的类型注解

类型注解的语法

基础语法:变量:类型

# 基础数据类型注解
var1: int = 10
var2: float = 3.1515926
var3: bool = True
var_4: str = "boost"
# 类对象类型注解
class Student:
pass
stu: Student = Student()
# 基础容器类型注解
my_list: list = [1, 2, 4]
my_tuple: tuple = (1, 2, 3)
my_set: set = {1, 2, 4}
my_dict: dict = {"name": "张三"}
my_str: str = "李四"
# 容器类型详细注解
"""
1. 元组类型设置类型详细注解,需要将每一个元素都标记出来
2. 字典类型设置类型详细注解,需要2个类型,第一个是key,第二个是value
"""
my_list1: list[int] = {1, 2, 4}
my_tuple1: tuple[str, int, bool] = ("张三", 34, True)
my_set1: set[int] = {1, 2, 4}
my_dict1: dict[str, int] = {"name": "张三"}

除了使用 变量: 类型, 这种语法做注解外,也可以在注释中进行类型注解。

语法:

#type: 类型

# 在注释中进行类型注解
class Student:
pass
var_1 = random.randint(1, 10) # type:int
var_2 = json.loads(data) # type:dict[str,int]
var_3 = func() # type:Student

tips:一般,无法直接看出变量类型之时会添加变量的类型注解。

类型注解的限制

类型注解主要功能在于:

  • 帮助第三方IDE工具对代码进行类型判断,协助做代码提示
  • 帮助开发者自身对变量进行类型注释(备注)

并不会真正的对类型做验证和判断,也就是说,类型注解仅仅是提示性的,不是决定性的。

var_1: int = "张三"
var_2: str = 123
# 该代码是不会报错的

总结

7.2 函数(方法)的类型注解

7.2.1 函数(方法)的类型注解 - 形参注解

函数和方法的形参类型注解语法:

def 函数方法名(形参名:类型,形参名:类型,.......):
pass
def add(x: int, y: int):
return x + y add(1, 3) def func(data: list):
data.append(1)
7.2.2 函数(方法)的类型注解 - 返回值注解

函数(方法)的返回值也是可以添加类型注解的。语法如下:

def 函数方法名(形参:类型,形参:类型, .....) -> 返回值类型:
pass
def add(x: int, y: int) -> int:
return x + y def func(data: list[int]) -> list[int]:
pass
7.2.3 总结

7.3 Union类型

使用Union[类型,...,类型]可以定义联合类型注解

mylist: list[int] = [1, 2, 3]
my_dict: dict[str, int] = {"age": 31, "num": 1}
mylist = [1, 2, "name"]
my_dict = {"name": "周杰伦", "age": 43}
from typing import Union
mylist: list[Union[str, int]] = [1, 2, "name"]
my_dict: dict[str, Union[str, int]] = {"name": "周杰伦", "age": 43}
# Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用。
my_list: list[Union[int, str]] = [1, 2, "张三", "李四"]
my_dict: dict[Union[int, str]] = [1, 2, "张三", "李四"]
def func(data: Union[int, str]) -> Union[int, str]:
pass

总结:

七、案例

7.1 学生信息录入

基本需求

实现代码:

class Student:
def __init__(self, name, age, address, count):
self.name = name
self.age = age
self.address = address
self.count = count
print(f"学生{count}信息录入完成,信息为:【学生姓名:{self.name},年龄:{self.age},地址:{self.address}】")
count += 1
for i in range(1, 11):
print(f'当前录入第{i}位学生信息,总共需录入10位学生信息')
name = input("请输入学生姓名:")
age = input("请输入学生年龄:")
address = input("请输入学生地址:")
student = Student(name, age, address, i)

7.2 数据分析案例

某公司,有2份数据文件,现需要对其进行分析处理,计算每日的销售额并以柱状图表的形式进行展示。

数据内容

1月份数据是普通文本,使用逗号分割数据记录,从前到后分别是(日期,订单id,销售额,销售省份)

2月份数据是JSON数据,同样包含(日期,订单id,销售额,销售省份)

需求分析

实现代码如下:

数据定义:data_define.py

"""
数据定义的类
""" class Record:
def __init__(self, date, order_id, money, province):
self.date = date # 订单日期
self.order_id = order_id # 订单ID
self.money = money # 订单金额
self.province = province # 销售省份 def __str__(self):
return f"订单日期={self.date},订单ID={self.order_id},订单金额={self.money},销售省份={self.province}"

操作文件:file_define.py

"""
和文件相关的类定义
"""
import json # 导包
from data_define import Record
# 先定义一个抽象类用来做顶层设计,确定有哪些功能需要实现
class FileReader:
# 抽象方法
def reader_data(self) -> list[Record]:
# 读取文件数据,读到的每一条数据都转换为Record对象,将他们都封装到list内返回即可
pass class TextFileReader(FileReader): def __init__(self, path):
self.path = path # 定义成员变量记录文件路径 # 复写(实现抽象方法)父类的方法
def reader_data(self) -> list[Record]:
f = open(self.path, "r", encoding="UTF-8") record_list: list[Record] = []
for line in f.readlines():
line = line.strip() # 消除读取到的每一行数据中的\n
data_list = line.split(",")
record = Record(data_list[0], data_list[1], int(data_list[2]), data_list[3])
record_list.append(record)
f.close()
return record_list class JsonFileReader(FileReader):
def __init__(self, path):
self.path = path # 定义成员变量记录文件路径 # 复写(实现抽象方法)父类的方法
def reader_data(self) -> list[Record]:
f = open(self.path, "r", encoding="UTF-8") record_list: list[Record] = []
for line in f.readlines():
data_dict = json.loads(line)
record = Record(data_dict["date"], data_dict["order_id"], int(data_dict["money"]), data_dict["province"])
record_list.append(record)
f.close()
return record_list # 测试使用
if __name__ == '__main__':
text_file_reader = TextFileReader("2011年1月销售数据.txt")
json_filer_reader = JsonFileReader("2011年2月销售数据JSON.txt")
list1 = text_file_reader.reader_data()
list2 = json_filer_reader.reader_data()
for l in list1:
print(l)
for l in list2:
print(l)

主文件:main.py

"""
面向对象,数据分析案例,主业务逻辑代码
实现步骤:
1.设计一个类,可以完成数据的封装
2.设计一个抽象类,定义文件读取的相关功能,并使用子类实现具体功能
3.读取文件,生产数据对象
4.进行数据需求的逻辑计算(计算每一天的销售额)
5.通过PyEcharts进行图形绘制
"""
from file_define import FileReader, TextFileReader, JsonFileReader
from data_define import Record
from pyecharts.charts import Bar
from pyecharts.options import *
from pyecharts.globals import ThemeType
text_file_reader = TextFileReader("2011年1月销售数据.txt")
json_file_reader = JsonFileReader("2011年2月销售数据JSON.txt") jan_data: list[Record] = text_file_reader.reader_data()
feb_data: list[Record] = json_file_reader.reader_data()
# 将2个月份的数据合并为一个list来存储
all_data: list[Record] = jan_data + feb_data # 开始进行数据计算
# {"2011-1-1": 1234, "2011-01-02": 100}
data_dict = {}
for record in all_data:
if record.date in data_dict.keys():
# 当前日期已经有记录了,所以和老记录做累加即可
data_dict[record.date] += record.money
else:
data_dict[record.date] = record.money # 可视化图表开发
bar = Bar(init_opts=InitOpts(theme=ThemeType.LIGHT)) bar.add_xaxis(list(data_dict.keys())) # 添加x轴的数据
bar.add_yaxis("销售额", list(data_dict.values()), label_opts=LabelOpts(is_show=False)) # 添加了y轴的数据
bar.set_global_opts(
title_opts=TitleOpts(title="每日销售额")
)
bar.render("每日销售额柱状图.html")

程序运行结果如下:

Python类与面向对象的更多相关文章

  1. 从C#到Python —— 4 类及面向对象

    http://www.cnblogs.com/yanxy/archive/2010/04/04/c2p_4.html 如果你熟悉C#,那么对类(Class)和面向对象(Object Oriented) ...

  2. 22 python 初学(类,面向对象)

    python: 函数式 + 面向对象 函数式可以做所有的事,是否合适? 面向对象: 一.定义: 函数: def + 函数名(参数) 面向对象: class  -> 名字叫 Bar 类 def   ...

  3. 22.python中的面向对象和类的基本语法

    当我发现要写python的面向对象的时候,我是踌躇满面,坐立不安呀.我一直在想:这个坑应该怎么爬?因为python中关于面向对象的内容很多,如果要讲透,最好是用面向对象的思想重新学一遍前面的内容.这个 ...

  4. python进阶01 面向对象、类、实例、属性封装、实例方法

    python进阶01 面向对象.类.实例.属性封装.实例方法 一.面向对象 1.什么是对象 #一切皆对象,可以简单地将“对象”理解为“某个东西” #“对象”之所以称之为对象,是因为它具有属于它自己的“ ...

  5. python 教程 第九章、 类与面向对象

    第九章. 类与面向对象 1)    类 基本类/超类/父类被导出类或子类继承. Inheritance继承 Inheritance is based on attribute lookup in Py ...

  6. 面向对象相关概念与在python中的面向对象知识(魔法方法+反射+元类+鸭子类型)

    面向对象知识 封装 封装的原理是,其成员变量代表对象的属性,方法代表这个对象的动作真正的封装是,经过深入的思考,做出良好的抽象(设计属性时用到),给出“完整且最小”的接口,并使得内部细节可以对外透明( ...

  7. Python如何设计面向对象的类(上)

    Python是一门高级语言,支持面向对象设计,如何设计一个符合Python风格的面向对象的类,是一个比较复杂的问题,本文提供一个参考,表达一种思路,探究一层原理. 目标 期望实现的类具有以下基本行为: ...

  8. Python如何设计面向对象的类(下)

    本文将在上篇文章二维向量Vector2d类的基础上,定义表示多维向量的Vector类. 第1版:兼容Vector2d类 代码如下: from array import array import rep ...

  9. Python - 面向对象编程 - 什么是 Python 类、类对象、实例对象

    什么是对象和类 https://www.cnblogs.com/poloyy/p/15178423.html Python 类 类定义语法 最简单的类定义看起来像这样 class ClassName: ...

  10. Python学习笔记之面向对象编程(三)Python类的魔术方法

    python类中有一些方法前后都有两个下划线,这类函数统称为魔术方法.这些方法有特殊的用途,有的不需要我们自己定义,有的则通过一些简单的定义可以实现比较神奇的功能 我主要把它们分为三个部分,下文也是分 ...

随机推荐

  1. Spring源码:Bean生命周期(三)

    前言 在之前的文章中,我们已经对 bean 的准备工作进行了讲解,包括 bean 定义和 FactoryBean 判断等.在这个基础上,我们可以更加深入地理解 getBean 方法的实现逻辑,并在后续 ...

  2. 微擎删除分类无法删除解决-select in效率低解决办法

    今天朋友微擎后台微网站里的分类要删除,可是怎么删除也不能删除,同样的系统另一套却可以迅速删除. 后来查询到是查询语句的问题,朋友的平台用户量太大,数据太大,用了以下语句,造成效率太低: SELECT ...

  3. 2020-11-16:手写代码:leetcode第406题。假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。

    福哥答案2020-11-16: ①排序.按照[身高]降序排列.如果[身高]一样,按照[人数]升序排列.②插入.遍历这个队列,按照[人数]插入相应位置. 采用leetcode里的代码,golang代码如 ...

  4. SpringBoot源码学习4——SpringBoot内嵌Tomcat启动流程源码分析

    系列文章目录和关于我 零丶引入 我在初学spring的时候,很懵逼,因为整个项目中不存在main方法,让我有点摸不着头脑.那时候我知道有个东西叫tomcat是它监听了端口,解析了协议调到了我的serv ...

  5. vue全家桶进阶之路14:常用属性和方法

    Vue2中常用的属性和方法: 属性 el:用于指定Vue实例挂载的元素,可以是CSS选择器.HTML元素或Vue组件. data:用于存储Vue实例的响应式数据,也可以是一个函数,返回一个对象,用于提 ...

  6. linux中使用jenkins自动部署前端工程

    1.去年在自己的服务器上安装了jenkins,说用来自己研究一下jenkins自动化部署前端项目,jenkins安装好了,可是一直没管,最近终于研究了一下使用jenkins自动化部署,以此记录下来. ...

  7. [NISACTF 2022]bingdundun~

    [NISACTF 2022]bingdundun~ 考点 文件上传.Phar://伪协议 一.题目 打开题目,发现是一道文件上传的题目,因为提示了可以压缩包,所以尝试直接上传zip文件,然后利用PHP ...

  8. GitHub上SSH keys和Deploy keys的区别

    平时安装一个git然后去GitHub进行SSH keys 配置最后就开始使用,然后换一台电脑再使用$ ssh-keygen -t rsa -C "your email"生成一个ss ...

  9. MassTransit实现Saga模式概览

    原文地址:Saga Overview 编排一系列事件的能力是一个强大的功能,而MassTransit使这成为可能. saga是由协调器管理的长期事务.saga是由事件发起的,saga编排事件,saga ...

  10. 通过实例了解vue3.3更新的特征

    开场白 5月份,vue团队发布了 vue3.3. 这次小版本的发布主要解决了-- Vue 与 TypeScript 一起使用时的许多长期存在的痛点. 下面我们一起来学习一下vue3.3新特征 准备新新 ...