目录
一、类的定义
基本语法
python与Java关于类的封装的区别
自定义构造方法
Java与Python的区别
源码
同一个类多种构造函数的构建
源码
二、魔法方法
基础部分
比较部分
与Java的区别
容器类型
三、属性管理
四、封装
基础部分
方法拓展
五、继承&多态
继承
多态
一、类的定义
基本语法
类的定义这两种都是可以的 # class Dog(object): # pass # class Dog: # pass
class Dog:
name = "小黑"
age=2
d = Dog()
print(f'name is {d.name},age is {d.age}')
python与Java关于类的封装的区别
# python与Java关于类的封装的区别: # python中没有的属性是可以拓展的,而Java不可以
class Dog:
name = "小黑"
age=2
d = Dog()
print(f'name is {d.name},age is {d.age}')
# python与Java关于类的封装的区别:
# python中没有的属性是可以拓展的,而Java不可以
d.sex ="女"
print(f'name is {d.name},age is {d.age},sex is {d.sex}')
自定义构造方法
Java与Python的区别
在Java中:直接给对象的属性赋值是不会报错的
在python中:直接给对象的属性赋值是会报错的,如图下
python中修改对象的属性的两种方法:
①:用对象点出要修改的属性 重新赋值
②:写一个方法
但是此时会存在一个问题,在实例化对象的时候,如果没有传入参数,则会报错
在Java中如果传入了参数则会修改为传入的参数,没有传入则会是原来的值
此时要解决该错,只需给参数设置一个默认值
源码
# 自定义构造方法
# class Dog:
# name = "小黑"
# age=2
#
# d = Dog()
# d.name = "旺财"
# print(f'name is {d.name},age is {d.age}')
# class Dog:
# name = "小黑"
# age=2
# def __init__(self,name,age): #self 等价于Java中的this
# self.name = name
# self.age = age
#
# d = Dog()
# # d.name = "旺财"
# print(f'name is {d.name},age is {d.age}')
class Dog:
def __init__(self,name="小黑",age=12): #self 等价于Java中的this
self.name = name
self.age = age
d = Dog()
# d.name = "旺财"
print(f'name is {d.name},age is {d.age}')
同一个类多种构造函数的构建
源码
class Dog:
def __init__(self,*args,**kwargs): #self 等价于Java中的this
if kwargs.get("name") != None:
self.name = kwargs.get("name")
if kwargs.get("age") != None:
self.age = kwargs.get("age")
d = Dog(name="小黑",age=13)
# d.name = "旺财"
print(f'name is {d.name},age is {d.age}')
二、魔法方法
python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两个下划线包围来命名的。 魔法方法可以使Python的自由度变得更高,在面向对象方面表现的更好。
基础部分
init 被用于初始化实例对象,new方法创建对象后就会调用该方法对实例的属性进行初始化
class Dog:
def __init__(self, name: str = "小黄", age: int = 12):
self.name = name
self.age = age
# d = Dog() # 不会报错
# d = Dog(name="小白") # 不会报错
d1 = Dog(name="小黑", age=20)
d = Dog(name=20, age="小黑") #报错
print(d)
print(f'name is {d.name};age is {d.age}')
会报警告
del 是析构方法,当对象的引用计数变为0时,这个对象会被销毁掉,此时就会调用del方法
类似于vue中的八大钩子函数
class T:
def __del__(self):
print("对象被销毁")
# 可以在这里做关闭连接 释放资源等事情
t = T()
# t指向0,此前创建的T的实例被销毁
print("1111")
t = 0
print("2222")
call 允许一个类的实例像函数一样被调用,这是一个非常重要的特性
class T:
def __call__(self, *args, **kwargs):
print("类的实例可以像函数一样被调用")
t = T()
t() # 相当于执行__call__方法体中的内容
len 是内置函数,len(t) 会调用实例的 len 方法
class T:
def __len__(self):
return 110
t = T()
print(len(t))
当被 str() 调用时, 调用该 str 方法
class Tu:
def __str__(self):
return f"我是{Tu.__name__}的一个实例"
t = Tu()
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)))
比较部分
lt(self, other)定义小于号的行为:x < y
le(self, other)定义小于等于号的行为:x <= y
eq(self, other)定义等于号的行为:x == y
ne(self, other)定义不等号的行为:x != y
gt(self, other)定义大于号的行为:x > y
ge(self, other)定义大于等于号的行为:x >= y
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(4)
print(s1 < s2)
print(s1 == s2)
print(s1 is s2)
与Java的区别
is比较的是地址 s1==s2 在Java中比较的是地址 而python比较的是值 在Java中比较值的是equals
容器类型
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 = dict()
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)
三、属性管理
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)中,对于属性的操作,都是在操作这个字典
python中对象的属性为什么可以动态变化?
类属性同样是存储在字典中,只是这个字典是类的字典
可以通过类名和对象名来调用,但是只能通过类名修改,类属性对于该类对象是共享的
类的属性和方法存在在类的 dict 之中
属性寻找规则: 先找实例的 dict ,再去查找类的 dict
四、封装
基础部分
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
book.price = 1
print(book._price)
使用 @property 装饰器修饰 price 方法后,你就可以像使用属性一样使用 price ,如果你希望可以对price 进行赋值,那么需要用 @price.setter 装饰器再装饰一个方法,该方法完成对 _price 属性的赋值操作。
我们以为自己直接操作了对象的属性,但其实我们是在使用类的方法,而且关键的是省去了调用方法时 的那对小括号
方法拓展
类方法 : 可以通过类名调用的方法 加上注解,修改参数为 cls (当前类),可以通过 cls 调用类的属性
静态方法 : 可以通过类名与对象来调用,但是无法使用类变量
class Book:
@classmethod
def run(cls):
print(cls.__name__)
# @staticmethod
# def say(cls):
# print(cls.__name__) #报错
# print("hello world")
@staticmethod
def say():
print("hello world")
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
book.price = 1
print(book._price)
Book.run()
book.run()
Book.say()
book.say()
# self -->this # cls --> 当前类
类方法 与 静态方法的区别就在于一个可以传参,一个不可以传参,这个参数指的是当前类
五、继承&多态
继承
如果没有指定基类,会默认继承 object 类, object 是所有类的基类,它提供了一些常见方法, 比如str
class Dog(object):
pass
类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
class A:
pass
class B:
pass
class C(A):
pass
class D(C):
pass
# class D(A,B):
# pass
#查看继承关系
print(D.__bases__)
print(D.__mro__)
属性及方法继承
class Father:
money = 100
def hello(self):
print("hello world")
class Son(Father):
pass
s = Son()
print(s.money)
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()
多态
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)