我有一个类有两个类方法(使用classmethod()函数)来获取和设置本质上是一个静态变量.我尝试使用property()函数,但它会导致错误.我能够在解释器中使用以下内容重现错误:
class Foo(object):
_var = 5
@classmethod
def getvar(cls):
return cls._var
@classmethod
def setvar(cls, value):
cls._var = value
var = property(getvar, setvar)
Run Code Online (Sandbox Code Playgroud)
我可以演示类方法,但它们不能作为属性:
>>> f = Foo()
>>> f.getvar()
5
>>> f.setvar(4)
>>> f.getvar()
4
>>> f.var
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
>>> f.var=5
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
Run Code Online (Sandbox Code Playgroud)
是否可以将property()函数与classmethod修饰函数一起使用?
在python中,我可以使用@classmethod装饰器向类添加方法.是否有类似的装饰器向类中添加属性?我可以更好地展示我在说什么.
class Example(object):
the_I = 10
def __init__( self ):
self.an_i = 20
@property
def i( self ):
return self.an_i
def inc_i( self ):
self.an_i += 1
# is this even possible?
@classproperty
def I( cls ):
return cls.the_I
@classmethod
def inc_I( cls ):
cls.the_I += 1
e = Example()
assert e.i == 20
e.inc_i()
assert e.i == 21
assert Example.I == 10
Example.inc_I()
assert Example.I == 11
Run Code Online (Sandbox Code Playgroud)
我上面使用的语法是可能的还是需要更多的东西?
我想要类属性的原因是我可以延迟加载类属性,这似乎足够合理.
可能重复:
python中的私有函数/变量实现
可以使用两个静态属性创建与以下类的等效项,一个是只读的,另一个是Python中的读写?
class Foo
{
private static string _rdy = "RO";
public static string rd
{
get { return _rd; }
}
private static string _rw = "RW";
public static string rw
{
get { return _rw ; }
set { _rw = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
我知道在Python中可以使用只读类属性,但我怎么没有在Python中看到任何读写类属性的例子.可能吗?基本上我想要:
class classproperty(object):
def __init__(self, getter
#, setter
):
self.getter = getter
# self.setter = setter
def __get__(self, instance, owner):
return self.getter(owner)
# Could there be a __set__ here?
#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv …Run Code Online (Sandbox Code Playgroud) 假设我正在制作带有物品的游戏(想想Minecraft,CS:GO武器,LoL和Dota物品等).游戏中可能存在大量相同的项目,但细节差异很小,例如条件/耐久性或项目中剩余的弹药数量:
player1.give_item(Sword(name='Sword', durability=50))
player2.give_item(Sword(name='Sword', durability=80))
player2.give_item(Pistol(name='Pistol', ammo=12))
Run Code Online (Sandbox Code Playgroud)
但是因为我不想每次都给我的剑和手枪命名(由于名字总是相同的),我希望它能够非常容易地创建新的项目类,我想我会name上课属性:
class Item:
name = 'unnamed item'
Run Code Online (Sandbox Code Playgroud)
现在我只是将其子类化:
class Sword(Item):
name = 'Sword'
def __init__(self, durability=100):
self.durability = durability
class Pistol(Item):
name = 'Pistol'
def __init__(self, ammo=10):
self.ammo = ammo
Run Code Online (Sandbox Code Playgroud)
我们有工作班:
>>> sword = Sword(30)
>>> print(sword.name, sword.durability, sep=', ')
Sword, 30
Run Code Online (Sandbox Code Playgroud)
但有没有办法以这种或那种方式使用SQLAlchemy 这些类属性(有时甚至是classproperties)?比如,我想将项目的持久性(实例属性)和名称(类属性)与其class_id(类属性)作为主键存储:
class Item:
name = 'unnamed item'
@ClassProperty # see the classproperty link above
def class_id(cls):
return cls.__module__ + '.' + cls.__qualname__
class Sword(Item): …Run Code Online (Sandbox Code Playgroud) 使用Python C-API 创建类属性(如此处和此处)的最佳方法是什么?静态属性也适用于我的情况.
跟进:
我试图实施牦牛的建议.我P在其槽tp_descr_get和tp_descr_set槽中定义了一个带有get和set函数的类.然后我在键下面的P类的类型对象的字典中添加了一个实例.然后Xp
x1 = X()
x2 = X()
x1.p = 10
print x1.p
print x2.p
print X.p
x2.p = 11
print x1.p
print x2.p
print X.p
Run Code Online (Sandbox Code Playgroud)
作品(前10张印刷三次,然后11张印刷三次),但是
X.p = 12
Run Code Online (Sandbox Code Playgroud)
失败并显示错误消息
TypeError: can't set attributes of built-in/extension type 'X'
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?
跟进2:
如果我分配了类型对象PyMem_Malloc并设置了Py_TPFLAGS_HEAPTYPE标志,那么一切正常; 我可以做到X.p = 12预期的结果.
如果我将类型对象保存在静态变量中并设置Py_TPFLAGS_HEAPTYPE标志,事情也会起作用,但这显然不是一个好主意.(但是为什么类型对象是在静态还是动态内存中呢?我从不让它的引用计数降到0.)
您只能在动态类型上设置属性的限制似乎很奇怪.这背后的理由是什么?
跟进3:
不,它不起作用.如果我将类型设置为X动态,X.p = …
有关于如何从静态方法访问静态变量(如大量的回答这一个,和那一个,而关于这个主题的伟大的信息在这里),但我在与其他方向的麻烦:如何使用静态方法初始化静态变量.例如:
import os, platform
class A(object):
@staticmethod
def getRoot():
return 'C:\\' if platform.system() == 'Windows' else '/'
pth = os.path.join(A.getRoot(), 'some', 'path')
Run Code Online (Sandbox Code Playgroud)
最后一行给出了一个例外:NameError: name 'A' is not defined.如果我使用@classmethod而不是,则会发生同样的错误@staticmethod.
是否可以从类变量访问静态方法?
假设我有一个像这样的 Python 枚举:
from enum import Enum
class FRUIT(Enum):
APPLE = 1
BANANA = 2
LEMON = 3
ORANGE = 4
Run Code Online (Sandbox Code Playgroud)
我想以有用的方式对它们进行“子集化”,比如可以说:
if fruit in FRUIT.CITRUS:
make_juice()
Run Code Online (Sandbox Code Playgroud)
我在某个地方定义了:CITRUS = {LEMON, ORANGE}。
我想将子集保留为主枚举的属性,因为它会在上下文中保留子集的使用。
我知道我可以做这样的事情,但我强烈希望避免使用方法调用符号。而且每次需要时重建集合似乎很浪费:
@classmethod
def CITRUS(cls):
return {cls.LEMON, cls.ORANGE}
Run Code Online (Sandbox Code Playgroud)
有没有办法在枚举元类完成其工作后添加类属性而不破坏事物?
我很好奇是否有更好的方法来实现这样的目标?我的意图是避免不必要的样板.提供的示例显然非常简单,让其他人了解我的想法.
def create_parametrized_class(animal):
class SomeClass:
def __init__(self, name):
self.name = name
def __str__(self):
return "{}: {}".format(animal, self.name)
return SomeClass
class Cat(create_parametrized_class("Cat")):
pass
class Dog(create_parametrized_class("Dog")):
pass
cat = Cat("Micka")
dog = Dog("Rex")
assert str(cat) == "Cat: Micka", "Cats..."
assert str(dog) == "Dog: Rex", "Dogs..."
Run Code Online (Sandbox Code Playgroud) python ×8
properties ×3
class ×1
class-method ×1
enums ×1
inheritance ×1
oop ×1
python-2.7 ×1
python-3.6 ×1
python-3.x ×1
python-c-api ×1
sqlalchemy ×1
static ×1