首页 > 编程语言 >python风格对象的实现方法

python风格对象的实现方法

时间:2024-08-30 21:24:20浏览次数:13  
标签:__ name setattr python self 对象 风格 方法 属性

文章目录

python风格对象的实现方法

前言

Keep it simple,stupid

不要为了满足过度设计的接口契约和让编译器开心,而去实现不需要的方法,我们要遵守 KISS 原则

class Vector2d:
    typecode = 'd'
    def __init__(self,x,y):
        self.__x = float(x)
        self.__y = float(y)
        self._l = 1
        self.__l = 1
        
    def __hash__(self):
        return hash(self.x) ^ hash(self.y)

    def __iter__(self):
        # 元祖表达式返回的是一个迭代器generator
        return ( i for i in (self.x,self.y))

    def __repr__(self):
        class_name = type(self).__name__
        return '{}({!r}, {!r})'.format(class_name, *self)

    def __str__(self):
        return str(tuple(self))

    def __bytes__(self):
        return (bytes([ord(self.typecode)])+bytes(array(self.typecode, self)))

    def __bool__(self):
        return bool(0)

    def __eq__(self, other):
        if isinstance(other,self.__class__):
            return self.x == other.x and self.y == other.y
        return False

    def __format__(self, format_spec=''):
        if format_spec == 'r':
            return f"({self.y}, {self.x})"
        else:
            return f"({self.x}, {self.y},haha)"
        
    def __abs__(self):
        return abs(self.x)

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self,value):
        self.__x = value

    @property
    def y(self):
        return self.__y

    def ldsx1(self):
        print(self.y,'aa')
        return self.y

init

__init__ 方法中设置属性时,会执行 __setattr__ 方法。

在 Python 中,当在 __init__ 方法中设置属性时,会调用 __setattr__ 方法来实际设置属性的值。这意味着 __setattr__ 方法在对象初始化期间会被调用。

以下是一个修正后的示例代码来说明这一点:

class MyClass:
    def __init__(self):
        self.attribute = 0

    def __setattr__(self, name, value):
        print("__setattr__ called")
        super().__setattr__(name, value)

obj = MyClass()

输出结果为:

__setattr__ called

可以看到,在 __init__ 方法中设置属性时,__setattr__ 方法被调用,并打印了相应的信息。

repr

repr() 以便于开发者理解的方式返回对象的字符串表示形式,实现__reper__的作用就是支持repr()方法

print(repr(实例))打印的就是__repr__实现的内容

str

str() 以便于用户理解的方式返回对象的字符串表示形式,实现__str__的作用就是支持str()方法

print(实例)打印的就是__str__实现的内容,print()默认获取str方法

iter(变成可迭代对象,优先级高于getitem)

把实例变成可迭代对象,可以直接return generator也可以yield

当同时实现了 __iter____getitem__ 方法时,__iter__ 方法具有更高的优先级。这意味着如果一个对象既实现了 __iter__ 方法又实现了 __getitem__ 方法,那么在迭代该对象时,Python 会首先尝试调用 __iter__ 方法。

在迭代对象时,__iter__ 方法被首先调用。而在索引访问对象时,__getitem__ 方法被调用。

因此,在同时实现了 __iter____getitem__ 方法时,__iter__ 方法具有更高的优先级。但如果只实现了 __getitem__ 方法,而没有实现 __iter__ 方法,则会直接使用 __getitem__ 方法进行迭代和索引访问。

如果没有 itercontains 方法,Python 会调用 getitem 方法,设法让迭代和 in 运算符可用。

contains(实用in运算符时调用)

用于判断对象是否包含某个元素。它在使用 in 运算符时被调用

当定义了一个类,并且希望该类的实例能够支持 in 运算符来检查是否包含某个元素时,可以在类中实现 __contains__ 方法。

下面是一个示例来说明 __contains__ 的作用:

class MyContainer:
    def __init__(self, items):
        self.items = items

    def __contains__(self, item):
        return item in self.items

my_container = MyContainer([1, 2, 3, 4, 5])

print(3 in my_container)  # 输出: True
print(6 in my_container)  # 输出: False

如果没有 itercontains 方法,Python 会调用 getitem 方法,设法让迭代和 in 运算符可用。

eq

可以让实例可以进行比较 可使用==方法,如果不重写应该默认比对实例的内存地址是否一致

abs

用于计算对象的绝对值。当你对一个对象调用内置的 abs() 函数时,会自动调用该对象的 __abs__ 方法来执行相应的操作。

abs(实例)

bool

用于确定对象的布尔值。当需要将一个实例作为条件表达式进行布尔判断时,会自动调用该对象的 __bool__ 方法来执行相应的操作。bool(实例触发)

根据默认规则,如果一个类没有定义 __bool__ 方法,则会尝试调用其父类(如果有的话)的 __bool__ 方法。如果没有找到任何定义的 __bool__ 方法,则会尝试调用 __len__ 方法(如果定义了),并根据返回值是否为零来确定布尔值。如果既没有定义 __bool__ 方法,也没有 __len__ 方法,则对象的布尔值默认为 True

format

在我们的示例中,如果传入的格式规范字符串为 'r',则 __format__ 方法返回反转的坐标形式 (y, x)。否则,它将返回默认的坐标形式 (x, y)

通过重写 __format__ 方法,你可以自定义对象的格式化输出,以适应特定的需求。你可以根据实际情况和格式规范字符串来编写逻辑,从而生成你想要的格式化结果。

hash

在 Python 类中,如果你希望对象能够被正确地用作键(key)存储在散列数据结构(如字典)中,你需要实现两个特殊方法:__hash__()__eq__()

  1. __hash__() 方法:这个方法返回一个整数值,表示对象的哈希值。哈希值用于确定对象在散列数据结构中的存储位置。对于可变对象来说,默认情况下是没有实现 __hash__() 方法的,因为可变对象的哈希值可能会发生改变。但是,不可变对象(如字符串、元组)默认实现了该方法。
  2. __eq__() 方法:这个方法用于比较两个对象是否相等。在散列数据结构中,在两个对象的哈希值相等的情况下,会调用 __eq__() 方法进行进一步的比较。如果不实现 __eq__() 方法,默认比较的是对象的身份标识(即内存地址),这通常不是我们想要的行为。

通过实现这两个方法,你可以确保对象在散列数据结构中被正确处理。__hash__() 方法提供了对象的哈希值以便快速查找,而 __eq__() 方法用于确保散列冲突时能够正确判断对象相等性。

需要注意的是,当你自定义类时,默认情况下继承自 object 的类已经实现了适当的 __hash__()__eq__() 方法。但是,如果你自定义了 __eq__() 方法,则通常也需要相应地自定义 __hash__() 方法,以确保两个相等的对象具有相同的散列值。

总而言之,为了正确使用自定义类对象作为键存储在散列数据结构中,你需要实现 __hash__() 方法来提供哈希值,并且最好也实现 __eq__() 方法来确保正确比较对象的相等性。这样可以保证在键的查找和比较时得到期望的结果。

getitem(实现切片,在无iter,contains时候会默认调用代替)

  • __getitem__ 方法用于通过索引访问对象中的元素。当你使用类似 obj[index] 的语法时,会自动调用该对象的 __getitem__ 方法,将索引作为参数传递给该方法。
  • 可索引对象可以是任何支持按索引访问的数据结构,例如列表、字典、字符串等。
  • __getitem__ 方法中,你可以根据传递的索引值执行相应的操作,并返回对应的元素。如果索引超出范围,则可以引发 IndexError 异常。
  • __iter__ 用于返回一个迭代器对象,使对象可以通过迭代方式访问元素。
  • __getitem__ 用于根据索引值获取对象中的元素,使对象可以像序列一样按索引进行访问。
 def __getitem__(self, index):
        cls = type(self)
        if isinstance(index, slice):
            return cls(self._components[index])
        elif isinstance(index, numbers.Integral):
            return self._components[index]
        else:
            msg = '{.__name__} indices must be integers'
            raise TypeError(msg.format(cls))

在上述代码中,cls(self._components[index])self._components[index] 是两种不同的操作。

  • self._components[index]:这是直接访问对象的 _components 属性,并使用索引 index 获取对应的元素。这是一种直接的访问方式,返回的是 _components 中索引位置处的值。
  • cls(self._components[index]):这是通过调用类的构造函数创建一个新的类实例。该实例的 _components 属性是根据索引 index 在原 _components 上进行切片操作得到的结果。这种方式可以用于创建一个包含部分元素的新对象。

总结来说,self._components[index] 返回的是 _components 中索引位置处对应的值,而 cls(self._components[index]) 创建了一个新的类实例,其中的 _components 是根据索引截取后的结果。具体使用哪种方式取决于需要何种行为和返回类型。

setitem

  • __setitem__ 方法被用于实现映射类型(如字典)的对象,例如通过索引访问元素。

  • __setitem__(self, key, value)

    • 用于映射类型的对象,例如自定义的字典类。

    • 在给对象的键(或索引)赋值时调用。

    • 接受三个参数:self 是当前对象,key 是要设置的键,value 是要设置的值。

    • 可以使用 obj[key] = value 的形式来调用该方法。

    • 示例代码:

      class MyDict:
          def __init__(self):
              self.data = {}
      
          def __setitem__(self, key, value):
              self.data[key] = value
      
      my_dict = MyDict()
      my_dict['key1'] = 'value1'  # 调用 __setitem__
      

len

__len__ 是一个特殊方法,用于返回对象的长度或大小。它是 Python 内置的一个魔术方法,可以通过调用 len(object) 来触发。

当你在自定义类中实现了 __len__ 方法时,就可以对该类的实例应用内置函数 len() 来获取对象的长度信息。

getattr

__getattr__ 是 Python 中的一个特殊方法,用于在访问不存在的属性时进行处理。当你使用点号(.)访问一个对象的属性,而该属性不存在时,Python 会尝试调用该对象的 __getattr__ 方法来处理这个情况。

下面是一个示例,演示如何定义和使用 __getattr__ 方法:

class Database:
    def __init__(self):
        self.data = {
            "user1": "password1",
            "user2": "password2"
        }
    
    def __getattr__(self, name):
        if name.startswith("get_password_"):
            username = name[len("get_password_"):]
            return self.get_password(username)
        else:
            raise AttributeError(f"'Database' object has no attribute '{name}'")
    
    def get_password(self, username):
        return self.data.get(username)

# 使用 Database 类
db = Database()

# 获取 user1 的密码
password = db.get_password_user1
print(password)  # 输出: password1

# 尝试获取不存在的属性
attribute_error = db.some_attribute  # 抛出 AttributeError 异常

在上述示例中,我们定义了一个名为 Example 的类,并实现了 __getattr__ 方法。当我们通过 obj.foo 访问对象 obj 的属性 foo 时,由于该属性不存在,Python 会自动调用 __getattr__ 方法,并将属性名作为参数传递给该方法。在我们的示例中,__getattr__ 方法会打印一条消息,并返回 None

需要注意的是,__getattr__ 方法只会在访问不存在的属性时被调用一次。如果在之后再次访问相同的不存在的属性,它将不会被触发,而是直接返回 AttributeError 异常。

除了 __getattr__ 方法,还有一个相关的方法 __getattribute__,它会在每次访问属性时都被调用,而不仅仅是在访问不存在的属性时。请根据具体需求选择合适的方法进行处理。

在实际开发中,__getattr__ 方法可以用于动态地处理对象属性的访问和获取。它提供了一种灵活的方式来处理属性不存在的情况,并可以根据需要进行自定义操作。

以下是一些在实际开发中使用 __getattr__ 方法的常见场景:

  1. 延迟加载:可以将某些属性的计算或获取延迟到实际访问时再执行,从而提高性能和效率。在 __getattr__ 方法中,你可以根据属性的名称动态地加载和返回属性值。
  2. 动态属性:根据不同的属性名称,返回不同的属性值。你可以根据需要在 __getattr__ 方法中编写逻辑,根据属性名称返回相应的值。
  3. 代理操作:当对象本身无法满足某个属性的需求时,可以使用 __getattr__ 方法将属性获取的操作委托给其他对象来处理。这样可以实现属性的动态转发。
  4. 错误处理:当访问不存在的属性时,可以通过 __getattr__ 方法捕获这些错误,并采取相应的处理措施,以防止程序崩溃或异常抛出。

需要注意的是,__getattr__ 方法只会在访问不存在的属性时被调用。对已经存在的属性,Python 不会调用该方法。如果要在每次访问属性时都进行处理,包括已存在的属性,可以使用 __getattribute__ 方法。

在实际开发中,你可以根据具体需求和场景,合理利用 __getattr__ 方法来增强对象的灵活性和功能。

setattr

在__init__的时候 会马上去_stattr__中进行实例存储_dict

__setattr__ 是 Python 中的一个特殊方法,用于在给属性赋值时进行处理。当你使用赋值语句给对象的属性赋值时,Python 会尝试调用对象的 __setattr__ 方法来处理这个操作。

__setattr__ 方法可以用于自定义属性赋值的行为,例如对属性值进行验证、记录赋值历史、限制属性的修改等。

下面是一个示例,演示如何定义和使用 __setattr__ 方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __setattr__(self, name, value):
        if name == "age" and value < 0:
            raise ValueError("Age cannot be negative")
        else:
            super().__setattr__(name, value)

# 使用 Person 类
person = Person("John", 25)
print(person.name)  # 输出: John
print(person.age)   # 输出: 25

person.age = -10   # 尝试给年龄赋值为负数,抛出 ValueError 异常

输出结果:

Setting attribute: foo = 42

在上述示例中,我们定义了一个名为 Example 的类,并实现了 __setattr__ 方法。当我们通过赋值语句 obj.foo = 42 给对象 obj 的属性 foo 赋值时,Python 会自动调用 __setattr__ 方法,并将属性名和属性值作为参数传递给该方法。在我们的示例中,__setattr__ 方法会打印一条消息,并将属性名和属性值存储到对象的 __dict__ 属性中。

需要注意的是,在 __setattr__ 方法内部,如果直接对属性进行赋值,会导致无限递归调用 __setattr__ 方法。为了避免这种情况,我们可以使用 self.__dict__[name] = value 来绕过 __setattr__ 方法并直接操作对象的属性字典。

在重写 __setattr__ 方法时,通常需要调用父类的 __setattr__ 方法来处理属性赋值的默认行为。这是因为 __setattr__ 方法是一个特殊方法,负责处理对象属性的赋值操作。如果我们完全重写了 __setattr__ 方法而没有调用父类的方法,将会导致一些重要的功能失效,例如:

  1. 阻止无限递归调用:在 __setattr__ 方法中直接使用 self.__setattr__(name, value) 进行属性赋值,会导致无限递归调用自身的 __setattr__ 方法。通过调用父类的 __setattr__ 方法,可以避免无限递归的问题。
  2. 保留属性字典的默认行为:父类的 __setattr__ 方法负责维护对象的属性字典,将属性名和属性值保存在 self.__dict__ 中。如果不调用父类的方法,属性赋值将不会被正确地保存在 self.__dict__ 中,可能导致对象无法正常工作。
  3. 其他继承的功能:通过调用父类的 __setattr__ 方法,我们可以保留其他可能由父类提供的功能或逻辑,确保子类在赋值属性时能够获得完整的继承特性。

因此,为了避免上述问题,并确保对象的属性赋值行为符合预期,通常需要在重写的 __setattr__ 方法中调用父类的 __setattr__ 方法。这样可以将控制流程交给父类处理默认行为,同时允许我们添加自定义的逻辑或修改默认行为。

在实现 __setattr__ 方法时,不直接修改 __dict__ 是推荐的做法。

__setattr__ 方法用于在给对象属性赋值时进行拦截和处理。通常,我们会使用 self.__dict__[name] = value 或者 super().__setattr__(name, value) 的方式将属性存储在对象的 __dict__ 中。

直接使用 self.__dict__[name] = value 的方式可以绕过 __setattr__ 方法,可能导致特殊逻辑或校验被绕过,从而引入潜在的错误或意外行为。

使用 super().__setattr__(name, value) 的方式可以确保遵循属性赋值的规范,并触发所需的逻辑,例如类型检查、拦截器等。

下面是一个示例,展示了如何在自定义类中实现 __setattr__ 方法:

class MyClass:
    def __init__(self):
        self._data = {}

    def __setattr__(self, name, value):
        if name.startswith("_"):
            super().__setattr__(name, value)
        else:
            self._data[name] = value

obj = MyClass()
obj.name = "John"  # 调用 __setattr__
print(obj.name)    # 输出: John

在上述代码中,当我们给 obj 对象的属性赋值时,__setattr__ 方法会被调用。如果属性名以 “_” 开头,则使用 super().__setattr__(name, value) 将属性存储在对象的 __dict__ 中;否则,将属性存储在 _data 字典中。这样,我们可以有选择地进行属性赋值的处理和存储。

dict

在 Python 中,__dict__ 是一个特殊的属性,它是对象的一个字典,用于存储对象的属性和方法。

每个对象都有一个 __dict__ 属性,它是一个字典(或其他可映射对象),其中的键是属性名,值是属性的值。通过 obj.__dict__ 可以访问对象的 __dict__ 属性。

下面是一个简单的示例,展示了如何使用 __dict__ 属性来查看对象的属性和方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def say_hello(self):
        print("Hello!")

person = Person("John", 25)

print(person.__dict__)  # 输出: {'name': 'John', 'age': 25}

person.city = "New York"

print(person.__dict__)  # 输出: {'name': 'John', 'age': 25, 'city': 'New York'}

在上述示例中,我们定义了一个 Person 类,并创建了一个 person 对象。通过 person.__dict__,我们可以查看 person 对象的属性字典。

初始时,person 对象的属性字典包含了 nameage 两个键值对。当我们为 person 对象动态添加一个新的属性 city 后,该属性也会出现在 __dict__ 字典中。

需要注意的是,由于 __dict__ 是一个字典,所以它具有字典的特性,例如可以使用 keys()values()items() 等方法来查看字典的键、值和键值对。但是,直接修改 __dict__ 可能会绕过对象的属性访问控制和一些特殊行为,因此应该小心使用。

在 Python 中,我们不能直接重写 __dict__ 属性因为它是一个特殊的属性而不是一个可重写的方法。__dict__ 是由解释器自动创建和管理的对象字典,用于存储对象的属性和方法。

然而,我们可以通过重写 __getattr____setattr__ 方法来控制属性的访问和赋值行为。下面是一个示例,演示了如何通过重写这两个方法来自定义对象的属性字典:

class CustomDict:
    def __init__(self):
        self._custom_dict = {}
    
    def __getattr__(self, name):
        return self._custom_dict.get(name)
    
    def __setattr__(self, name, value):
        self._custom_dict[name] = value

obj = CustomDict()
obj.name = "John"
obj.age = 25

print(obj.__dict__)  # 输出: {'_custom_dict': {'name': 'John', 'age': 25}}
print(obj.name)      # 输出: John
print(obj.age)       # 输出: 25

在上述示例中,我们创建了一个名为 CustomDict 的类,并在其内部使用一个名为 _custom_dict 的字典属性来代替默认的 __dict__。通过重写 __getattr__ 方法,当我们访问对象的属性时,会从 _custom_dict 中获取相应的值。通过重写 __setattr__ 方法,当我们为对象赋值属性时,会将属性名和属性值保存到 _custom_dict 中。

需要注意的是,这只是一种近似于重写 __dict__ 的方式,并且在某些情况下可能会有一些限制和副作用。一般来说,直接操作 __dict__ 是不常见且不推荐的做法,通常更好地利用 Python 提供的属性访问控制机制和特殊方法来管理对象的属性字典。

slots

默认情况下,Python 在各个实例中名为_dict_ 的字典里存储实例属性。为了使用底层的散列表提升访问速度,字典会消耗大量内存。如果要处理数百万 个属性不多的实例,通过 slots 类属性,能节省大量内存,方法是让解释器在元 组中存储实例属性,而不用字典。

定义 slots 的方式是,创建一个类属性,使用 slots 这个名字,并把它的 值设为一个字符串构成的可迭代对象,其中各个元素表示各个实例属性。我喜欢使用元 组,因为这样定义的 slots 中所含的信息不会变化

class Vector2d:
    __slots__ = ('__x', '__y')

typecode = ‘d’

在类中定义 slots 属性的目的是告诉解释器:“这个类中的所有实例属性都在这 儿了!”这样,Python 会在各个实例中使用类似元组的结构存储实例变量,从而避免使 用消耗内存的 dict 属性。如果有数百万个实例同时活动,这样做能节省大量内 存。

在类中定义 slots 属性之后,实例不能再有 slots 中所列名 称之外的其他属性。这只是一个副作用,不是 slots 存在的真正原因。不要 使用 slots 属性禁止类的用户新增实例属性。slots 是用于优化的, 不是为了约束程序员。

私有变量

如果以 __mood 的形式(两个前导下划线,尾部没有或最多有一个 下划线)命名实例属性,Python 会把属性名存入实例的 dict 属性中,而且会在 前面加上一个下划线和类名。因此,对 Dog 类来说,__mood 会变成 _Dog__mood; 对 Beagle 类来说,会变成 _Beagle__mood。这个语言特性叫名称改写(name mangling)。

>>> v1 = Vector2d(3, 4)
>>> v1.__dict__
{'_Vector2d__y': 4.0, '_Vector2d__x': 3.0}
>>> v1._Vector2d__x
3.0

也不是所有人都喜欢 self.__x 这种不 对称的名称。有些人不喜欢这种句法,他们约定使用一个下划线前缀编写“受保护”的属 性(如 self._x)。批评使用两个下划线这种改写机制的人认为,应该使用命名约定 来避免意外覆盖属性。本章开头引用了多产的 Ian Bicking 的一句话,那句话的完整表 述如下:

绝对不要使用两个前导下划线,这是很烦人的自私行为。如果担心名称冲突,应该 明确使用一种名称改写方式(如 _MyThing_blahblah)。这其实与使用双下划 线一样,不过自己定的规则比双下划线易于理解。

Python 解释器不会对使用单个下划线的属性名做特殊处理,不过这是很多 Python 程序 员严格遵守的约定,他们不会在类外部访问这种属性。遵守使用一个下划线标记对象 的私有属性很容易,就像遵守使用全大写字母编写常量那样容易。

最终案例

from array import array
import reprlib
import math
import numbers

import functools import operator import itertools ➊

class Vector:
    typecode = 'd'
    def __init__(self, components):
        self._components = array(self.typecode, components)
    def __iter__(self):
        return iter(self._components)
    def __repr__(self):
        components = reprlib.repr(self._components)
        components = components[components.find('['):-1]
        return 'Vector({})'.format(components)
    def __str__(self):
        return str(tuple(self))
    def __bytes__(self):
        return (bytes([ord(self.typecode)]) +
                bytes(self._components))
    def __eq__(self, other):
        return (len(self) == len(other) and
                all(a == b for a, b in zip(self, other)))
    def __hash__(self):
        hashes = (hash(x) for x in self)
        return functools.reduce(operator.xor, hashes, 0)
    def __abs__(self):
        return math.sqrt(sum(x * x for x in self))
    def __bool__(self):
        return bool(abs(self))
    def __len__(self):
        return len(self._components)
    def __getitem__(self, index):
        cls = type(self)
        if isinstance(index, slice):
            return cls(self._components[index])
        elif isinstance(index, numbers.Integral):
            return self._components[index]
        else:
            msg = '{.__name__} indices must be integers'
            raise TypeError(msg.format(cls))
    shortcut_names = 'xyzt'
    def __getattr__(self, name):
        cls = type(self)
        if len(name) == 1:
        	pos = cls.shortcut_names.find(name)
        if 0 <= pos < len(self._components):
            return self._components[pos]
    	msg = '{.__name__!r} object has no attribute {!r}'
    	raise AttributeError(msg.format(cls, name))
    	
    def angle(self, n): ➋
      r = math.sqrt(sum(x * x for x in self[n:])) 
      a = math.atan2(r, self[n-1])
      if (n == len(self) - 1) and (self[-1] < 0):
              return math.pi * 2 - a
          else:
      return a
      	
		def angles(self): ➌
			return (self.angle(n) for n in range(1, len(self)))

标签:__,name,setattr,python,self,对象,风格,方法,属性
From: https://blog.csdn.net/weixin_43322583/article/details/141690533

相关文章

  • Pyspark中的ROW对象使用
    文章目录Pyspark中的Row对象使用Row对象介绍Row对象创建使用Row对象创建DataFrameDataFrame转换为row对象Row对象包含的方法asDict()count()index()Pyspark中的Row对象使用Row对象介绍在PySpark中,Row对象是DataFrame的基本组成单元,它封装了DataFrame中的每一行数......
  • Python实现图片的拼接
    Python实现图片的拼接Python中有多种方法可以实现图片拼接,下面是一个使用Pillow库的示例:首先,你需要安装Pillow库:pipinstallpillow然后,可以使用以下代码实现图片拼接:fromPILimportImage#读取两张图片img1=Image.open('image1.jpg')img2=Image.open('imag......
  • python学习总结(一)
    @TOC<hrstyle="border:solid;width:100px;height:1px;"color=#000000size=1">1.变量元组类型b=()列表类型b=[]字典类型b={}简单类型b=123a=’123‘c=Trued=5.0命名规则1、开头必须以字母或下划线_开头2、区分大小写3、除了开头,其余字母、数字、下划线均......
  • 分享两个方法分析python打包exe
    在Python开发中,常常需要将Python脚本打包成独立的可执行文件,以便在没有Python环境的电脑上运行。你是否曾为此感到困惑,不知道该选择哪种工具来实现这一目标?其实,打包Python脚本并不难,关键在于选择合适的工具。今天,我们将介绍两种常用的Python打包工具:PyInstaller和auto-py-to-exe,让......
  • OpenVoiceV2:零样本跨语言语音克隆技术,支持多种风格控制
    1openvoicev2介绍语音克隆技术近年来取得了显著进展,但现有方法通常存在着局限性,例如无法灵活控制语音风格、需要大量多语言数据进行训练、生成速度慢等等。为了克服这些挑战,MyShell.ai团队推出了全新的语音克隆技术OpenVoiceV2,它能够在无需额外训练的情况下,仅凭少量参考音频......
  • 【有源码】基于Python的猫眼电影数据分析可视化与电影推荐系统K-means算法电影票房数
    注意:该项目只展示部分功能,如需了解,文末咨询即可。本文目录1.开发环境2系统设计2.1设计背景2.2设计内容3系统展示3.1功能展示视频3.2系统页面4更多推荐5部分功能代码1.开发环境开发语言:Python采用技术:K-means算法数据库:MySQL开发环境:PyCharm2系统......
  • C#之中SqlConnection的Close和Dispose的区别和在使用using语句管理SqlConnection对象
    SqlConnection的Close和Dispose的区别在C#中,SqlConnection对象的Close和Dispose方法都可以用来释放数据库连接资源,但它们的作用和使用场景有所不同。Close方法SqlConnection.Close方法用于关闭与数据库的连接。当你调用这个方法时,它会关闭连接,但不会释放与连接关联的所有......
  • python操作redis的数据类型(超详细!!)
    在Web应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候Web站点基本上访问和并发不高、交互也较少。而在后来,随着访问量的提升,使用关系型数据库的Web站点多多少少都开始在性能上出现了一些瓶颈,而瓶颈的源头一般是在磁盘的I/O上。而随着互联网技术的......
  • 【C#】一个喜欢用Python的菜狗在尝试Linq之后总结的常见用法以及示例
    1.筛选(Where)筛选集合中的元素。类似python中列表推导式中的if示例int[]numbers={1,2,3,4,5,6};varevenNumbers=numbers.Where(n=>n%2==0);foreach(varnuminevenNumbers){Console.WriteLine(num);}//输出:2,4,6python中的实现[if......
  • SAP B1 无对象表或者没有含自动增量的对象,如何通过SBO_SP_TransactionNotification控
       SAPB1中无对象或者没有含自动增量的对象表,在SBO_SP_TransactionNotification中object_type规则:-3+Tab键+@表名例如:创建无对象表IPS_OITM,则object_type值为:[-3@IPS_OITM]特别注意:如果用的是没有含自动增量的对象表,必须要在Name字段中输入值才会触发SBO控制的存储过程......