Я экспериментирую с метапрограммированием на Python (CPython 3.10.13) и заметил странное поведение с object.__new__ (ну, по крайней мере, странное для меня). Взгляните на следующий эксперимент (не практический код, просто эксперимент) и комментарии. Обратите внимание, что object.__new__, похоже, меняет свое поведение в зависимости от первого аргумента:
# Empty class inherit __new__ and __init__ from object
class Empty:
pass
# Confirmation of inheritance
assert Empty.__new__ is object.__new__, "Different __new__"
assert Empty.__init__ is object.__init__, "Different __init__"
empty_obj = Empty()
uinit_empty_obj = object.__new__(Empty)
assert type(empty_obj) is type(uinit_empty_obj), "Different types"
try:
object.__new__(Empty, 10, 'hi', hello='bye')
except TypeError as e:
# repr(e) mentioned the Empty class
print(repr(e))
# Overwrite the object __new__ and __init__ methods
# __new__ and __init__ with the same signature
class Person:
def __new__(cls, name, age):
"""Does nothing bassicaly. Just overwrite `object.__new__`."""
print(f'Inside {cls.__name__}.__new__')
return super().__new__(cls)
def __init__(self, name, age):
print(f'Inside {type(self).__name__}.__init__')
self.name = name
self.age = age
a_person = Person('John Doe', 25)
uinit_person = Person.__new__(Person, 'Michael', 40)
try:
# Seems an obvious error since object() doesn't take any arguments
another_uinit_person = object.__new__(Person, 'Ryan', 25)
except TypeError as e:
# Indeed raises TypeError, but now there isn't a mention of the Person class in repr(e)
print('`another_uinit_person` :', repr(e))
# Now, some weird things happen (well, weird for me).
# Inherit __new__ from object and overwrite __init__.
# __new__ and __init__ with unmatching signatures.
# A basic Python class. Works just fine like suppose to.
class Vehicle:
def __init__(self, model):
self.model = model
# Confirmation of __new__ inheritance.
assert Vehicle.__new__ is object.__new__, "Nop, it isn't"
a_vehicle = Vehicle('Honda')
# I would understand if CPython autogenerated a __new__ method matching __init__
# or a __new__ method that accepts all arguments.
# The following try-except-else suggests the last, but the assert statement above
# indicates that Vehicle.__new__ is actually object.__new__.
try:
# Doesn't raise any exceptions
uinit_vehicle = Vehicle.__new__(Vehicle, 'Honda', 10, ('whatafuck',), hello='bye')
except Exception as e:
print(repr(e))
else:
print('`uinit_vehicle` : constructed just fine', uinit_vehicle)
# Now the following runs just fine
try:
# Doesn't raise any exceptions
another_unit_vehicle = object.__new__(Vehicle, 'Toyota')
another_unit_vehicle = object.__new__(Vehicle, 'Toyota', 69, mygod='Jesus')
except Exception as e:
print(repr(e))
else:
print('`another_unit_vehicle` : constructed just fine:', another_unit_vehicle)
TypeError('Empty() takes no arguments')
Inside Person.__new__
Inside Person.__init__
Inside Person.__new__
`another_uinit_person` : TypeError('object.__new__() takes exactly one argument (the type to instantiate)')
`uinit_vehicle` : constructed just fine
`another_unit_vehicle` : constructed just fine:
Мои вопросы:
Почему в первом TypeError упоминается класс Empty и во-вторых, просто object.__new__?
Почему object.__new__(Person, 'Ryan', 25) вызвал TypeError и object.__new__(Vehicle , 'Toyota') и object.__new__(Vehicle, 'Toyota', 69, mygod='Jesus') нет?
По сути: что объект.__new__ делает под капотом?
Мне кажется, что он выполняет несколько странную проверку в методах переопределения __new__ и/или __init__ первого аргумента, если таковые имеются.
Я экспериментирую с метапрограммированием на Python (CPython 3.10.13) и заметил странное поведение с object.__new__ (ну, по крайней мере, странное для меня). Взгляните на следующий эксперимент (не практический код, просто эксперимент) и комментарии. Обратите внимание, что object.__new__, похоже, меняет свое поведение в зависимости от первого аргумента: [code]# Empty class inherit __new__ and __init__ from object class Empty: pass
# Confirmation of inheritance assert Empty.__new__ is object.__new__, "Different __new__" assert Empty.__init__ is object.__init__, "Different __init__"
assert type(empty_obj) is type(uinit_empty_obj), "Different types"
try: object.__new__(Empty, 10, 'hi', hello='bye') except TypeError as e: # repr(e) mentioned the Empty class print(repr(e))
# Overwrite the object __new__ and __init__ methods # __new__ and __init__ with the same signature class Person: def __new__(cls, name, age): """Does nothing bassicaly. Just overwrite `object.__new__`.""" print(f'Inside {cls.__name__}.__new__') return super().__new__(cls)
def __init__(self, name, age): print(f'Inside {type(self).__name__}.__init__') self.name = name self.age = age
try: # Seems an obvious error since object() doesn't take any arguments another_uinit_person = object.__new__(Person, 'Ryan', 25) except TypeError as e: # Indeed raises TypeError, but now there isn't a mention of the Person class in repr(e) print('`another_uinit_person` :', repr(e))
# Now, some weird things happen (well, weird for me). # Inherit __new__ from object and overwrite __init__. # __new__ and __init__ with unmatching signatures. # A basic Python class. Works just fine like suppose to. class Vehicle: def __init__(self, model): self.model = model
# Confirmation of __new__ inheritance. assert Vehicle.__new__ is object.__new__, "Nop, it isn't"
a_vehicle = Vehicle('Honda')
# I would understand if CPython autogenerated a __new__ method matching __init__ # or a __new__ method that accepts all arguments. # The following try-except-else suggests the last, but the assert statement above # indicates that Vehicle.__new__ is actually object.__new__. try: # Doesn't raise any exceptions uinit_vehicle = Vehicle.__new__(Vehicle, 'Honda', 10, ('whatafuck',), hello='bye') except Exception as e: print(repr(e)) else: print('`uinit_vehicle` : constructed just fine', uinit_vehicle)
# Now the following runs just fine try: # Doesn't raise any exceptions another_unit_vehicle = object.__new__(Vehicle, 'Toyota') another_unit_vehicle = object.__new__(Vehicle, 'Toyota', 69, mygod='Jesus') except Exception as e: print(repr(e)) else: print('`another_unit_vehicle` : constructed just fine:', another_unit_vehicle) [/code] Я получил следующий результат: [code]TypeError('Empty() takes no arguments') Inside Person.__new__ Inside Person.__init__ Inside Person.__new__ `another_uinit_person` : TypeError('object.__new__() takes exactly one argument (the type to instantiate)') `uinit_vehicle` : constructed just fine `another_unit_vehicle` : constructed just fine: [/code] Мои вопросы: [list] [*]Почему в первом TypeError упоминается класс Empty и во-вторых, просто object.__new__? [*]Почему object.__new__(Person, 'Ryan', 25) вызвал TypeError и object.__new__(Vehicle , 'Toyota') и object.__new__(Vehicle, 'Toyota', 69, mygod='Jesus') нет? [/list] [b]По сути:[/b] что объект.__new__ делает под капотом? Мне кажется, что он выполняет несколько странную проверку в методах переопределения __new__ и/или __init__ первого аргумента, если таковые имеются.
Я экспериментирую с метапрограммированием на Python (CPython 3.10.13) и заметил странное поведение с object.__new__ (ну, по крайней мере, странное для меня). Взгляните на следующий эксперимент (не практический код, просто эксперимент) и комментарии....
Что происходит, когда мы вызываем обратный метод функции потерь? Как в коде ниже
import torch.nn as nn
outputs = model(inputs) # Example ResNet18
criterion = nn.CrossEntropyLoss()
loss = criterion(outputs, labels)
loss.backward()
Пример с веб-страницы Newtonsoft «Сериализация и десериализация JSON»
Product product = new Product();
product.ExpiryDate = new DateTime(2008, 12, 28);
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new...