原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。
在 Python 中,类是对象的抽象模板,用于定义对象的属性和行为。
声明一个类的通用语法如下:
class ClassName:
# 类的属性和方法
其中,ClassName
为类的名称,类的属性和方法需要缩进一个层级来声明。
类的属性可以是实例属性和类属性。实例属性是每个对象单独拥有的属性,而类属性是所有对象共享的属性。类属性可以通过 ClassName.attribute
来访问,也可以通过 self.attribute
来访问,但是在类属性和实例属性名字相同时,实例属性具有更高的优先级。
类的方法可以是实例方法、类方法和静态方法。实例方法是针对对象的方法,其第一个参数为 self
,表示方法所属的对象。类方法是针对类的方法,其第一个参数为 cls
,表示方法所属的类。静态方法是不依赖于类或对象的方法,可以通过 ClassName.method
或者 self.method
调用。
下面是一个简单的示例,演示了如何声明一个类,并定义实例属性、类属性和实例方法:
class Person:
species = 'human' # 类属性
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
def say_hi(self):
print(f"Hi, my name is {self.name}. I'm {self.age} years old.")
# 创建对象并调用实例方法
p1 = Person('Alice', 25)
p1.say_hi()
# 访问类属性
print(Person.species)
这个示例中,Person
类具有 name
和 age
两个实例属性,以及 species
一个类属性,还有一个 say_hi()
实例方法,用来打印一个问候语。我们创建了一个对象 p1
,并通过 p1.say_hi()
调用了实例方法。另外,我们还通过 Person.species
访问了类属性。
通过构造函数 init() 来给类传值。构造函数是一种特殊的方法,用于初始化类的实例对象。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('Alice', 25)
print(p.name) # 输出 'Alice'
print(p.age) # 输出 25
在 Python 中,类中有三种方法:实例方法、类方法和静态方法。下面对这三种方法进行简单介绍:
self
,代表实例本身。通过调用实例来调用实例方法。实例方法可以访问实例中的属性和方法。class MyClass:
def instance_method(self, x):
print(f"Instance method called with {x}")
self.x = x # 修改实例属性
my_object = MyClass()
my_object.instance_method(42) # 调用实例方法
print(my_object.x) # 访问实例属性
@classmethod
装饰器定义的方法,第一个参数默认是 cls
,代表类本身。通过调用类来调用类方法。类方法可以访问类和类中的属性和方法。class MyClass:
class_variable = 100
@classmethod
def class_method(cls, x):
print(f"Class method called with {x}")
cls.class_variable += 1 # 修改类属性
MyClass.class_method(42) # 调用类方法
print(MyClass.class_variable) # 访问类属性
@staticmethod
装饰器定义的方法,与类和实例无关。通过调用类或实例来调用静态方法。静态方法不能访问类或实例中的属性和方法。class MyClass:
@staticmethod
def static_method(x):
print(f"Static method called with {x}")
MyClass.static_method(42) # 调用静态方法
需要注意的是,类方法和静态方法可以通过类和实例访问,但实例方法只能通过实例访问。此外,类方法可以用于创建工厂方法,静态方法则可以用于实现辅助函数或通用功能。
在 Python 中,没有真正的私有方法和私有变量,但可以使用以下约定来实现类似的效果:
用一个下划线 _
开头的方法或变量表示它是私有的,即不应该在类的外部使用。但这仅仅是个约定,实际上这些方法和变量仍然可以从类的外部访问。
用两个下划线 __
开头的方法或变量表示它是私有的,且不能从类的外部访问。这是通过 Python 解释器自动对名称进行重命名以实现的,例如 __foo
会被重命名为 _classname__foo
,所以从类的外部访问时会出现 AttributeError 错误。
下面是一个示例,演示如何定义私有方法和私有变量:
class MyClass:
def __init__(self):
self.public_variable = "I am public"
self._private_variable = "I am private"
self.__secret_variable = "I am a secret"
def public_method(self):
print("This is a public method")
def _private_method(self):
print("This is a private method")
def __secret_method(self):
print("This is a secret method")
my_object = MyClass()
print(my_object.public_variable) # 可以访问公共变量
print(my_object._private_variable) # 可以访问私有变量,但这是不推荐的做法
print(my_object._MyClass__secret_variable) # 可以通过名称重命名访问私有变量
my_object.public_method() # 可以调用公共方法
my_object._private_method() # 可以调用私有方法,但这是不推荐的做法
my_object._MyClass__secret_method() # 可以通过名称重命名调用私有方法,但这是不推荐的做法
这里演示了如何访问公共、私有和秘密变量和方法。请注意,虽然可以访问私有变量和方法,但这是不推荐的做法,因为它破坏了封装性和可维护性。建议仅在必要时使用私有变量和方法,并且遵循约定和最佳实践。
在 Python 中,类的封装是指通过设置类的访问权限,以隐藏类的属性和方法,防止外部程序对其进行非法访问和修改。Python 中的访问权限有三种:
下面是一个简单的示例,展示了如何使用上述访问权限:
class Shape:
def __init__(self, x, y):
self.x = x
self.y = y
self.__color = 'white' # 私有成员
self._opacity = 1.0 # 受保护成员
def get_color(self):
return self.__color # 获取私有成员
def set_color(self, color):
self.__color = color # 设置私有成员
class Circle(Shape):
def __init__(self, x, y, r):
super().__init__(x, y)
self.r = r
def get_opacity(self):
return self._opacity # 获取受保护成员
c = Circle(0, 0, 10)
print(c.x) # 输出 0
print(c.get_color()) # 输出 'white'
c.set_color('red') # 修改私有成员
print(c.get_color()) # 输出 'red'
在上面的代码中,我们定义了一个 Shape
基类和一个 Circle
子类。在 Shape
类中,我们定义了 x
、y
两个公有成员,__color
一个私有成员,_opacity
一个受保护成员。在 Circle
类中,我们继承了 Shape
类中的属性和方法,并定义了 r
属性。
我们创建了一个 Circle
实例对象 c
,并访问其公有成员 x
和 y
,输出结果为 0。我们调用 get_color()
方法获取私有成员 __color
的值,并输出结果为 'white'
。接着,我们调用 set_color()
方法修改私有成员 __color
的值,并调用 get_color()
方法输出结果为 'red'
。
需要注意的是,Python 中的私有成员和受保护成员并不是真正的私有和受保护,它们只是在名称前添加了一个特殊的前缀,以此来防止外部程序访问。但是,如果需要,仍然可以通过特殊的方法来访问和修改这些成员。
Mixin 是一种 Python 中的设计模式,可用于将可复用的功能添加到类中,而无需使用继承。Mixin 类是一种轻量级的类,其中定义了一些方法和属性,可以与其他类组合使用。Mixin 类的主要作用是将重复的代码封装在一个类中,并将其添加到多个类中,从而减少代码重复和增加代码的可维护性。
首先,我来举一个例子来解释 Mixin 的使用方式。假设我们有多个类需要实现缓存功能,我们可以使用 Mixin 类来实现:
class CacheMixin:
cache = {}
def get_cache(self, key):
return self.cache.get(key)
def set_cache(self, key, value):
self.cache[key] = value
class User:
def __init__(self, name, age):
self.name = name
self.age = age
class Customer:
def __init__(self, name, address):
self.name = name
self.address = address
class CachedUser(User, CacheMixin):
def __init__(self, name, age):
super().__init__(name, age)
class CachedCustomer(Customer, CacheMixin):
def __init__(self, name, address):
super().__init__(name, address)
在上面的代码中,我们定义了一个 CacheMixin
类,其中包含了缓存相关的方法和属性。然后,我们定义了两个类 User
和 Customer
。最后,我们定义了两个通过继承 User
和 Customer
类和 CacheMixin
类的类 CachedUser
和 CachedCustomer
,这两个类中就具有了缓存功能。这种方式使得我们可以在不破坏原有类结构的情况下,轻松地添加缓存功能到类中。
Mixin 类的设计也有一些原则需要遵循:
Mixin 类应该只是一个功能单一的类,只包含一个或多个相关的方法或属性,不应该尝试实现完整的类。
Mixin 类应该使用命名空间来避免与其他类冲突。
Mixin 类可以使用抽象类来强制子类实现指定的方法。
在多个 Mixin 类中出现名称冲突时,可以使用命名空间来避免这种情况。
总之,Mixin 设计模式是一种非常有用的技术,它可以帮助我们将复用的功能添加到类中,并提高代码的重用性和可维护性。
from pydantic import BaseModel, validator
class User(BaseModel):
name: str
age: int
@validator('name')
def name_must_contain_space(cls, v):
if ' ' not in v:
raise ValueError('Must contain a space')
return v
@validator('age')
def age_must_be_positive(cls, v):
if v < 0:
raise ValueError('Age must be positive')
return v
import json
import requests
import requests.auth
from django.conf import settings
CLIENT_ID = "xxxxx"
CLIENT_SECRET = "xxxxx"
Observe_HOST = 'http://192.168.1.0:8080'
TOKEN_URL = Observe_HOST + '/spacety/oauth2/token'
Mission_Edit_MgcType = Observe_HOST + '/spacety/imagingTasks/updateMgcType'
class ConnectObserve(object):
"""与api通信"""
def __init__(self):
self.token = None
def get_token(self):
client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)
post_data = {"grant_type": "client_credentials"}
response = requests.post(TOKEN_URL,
auth=client_auth,
data=post_data)
token_json = response.json()
print(token_json)
return token_json["access_token"]
# 修改成像任务的mgcType
def mission_edit_mgcType(self, data):
if not self.token:
self.token = self.get_token()
headers = {"Authorization": "Bearer " + self.token}
ret = requests.post(url=Mission_Edit_MgcType, data=json.dumps(data), headers=headers)
return ret.json()
class CommodityPic(object):
"""同步数据至商城"""
def __init__(self):
self.username = settings.COMMODITY.get('username')
self.password = settings.COMMODITY.get('password')
self.token = None
def get_token(self):
headers = {"Content-Type": "application/json"}
user_info = {
"username": self.username,
"password": self.password
}
s1 = requests.post(url=settings.COMMODITY.get('host') + '/rest/v01/user/login/',
json=user_info,
headers=headers)
if s1.status_code == requests.codes.ok:
req_data = s1.json()
self.token = req_data["token"]
return req_data["token"]
return None
def insert(self, pic_data):
if not self.token:
self.token = self.get_token()
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + self.token
}
try:
ret = requests.post(url=settings.COMMODITY.get('host') + "/pic_query/admin/picdata/",
data=json.dumps(pic_data),
headers=headers)
print('ret.json()', ret.json())
if ret.status_code == requests.codes.ok:
if ret.json().get('code') == 0:
return True
return False
except Exception as e:
print('同步数据至商城', e)
return False