Reputation: 3344
Currently I have something like
if name and password:
user = User(name, password)
...do stuff
I'd like to refactor it to something:
user = User(name, password)
if user:
...do stuff
I create a User()
class:
class User():
def __init__(self, name, password):
if name and password:
self.name, self.password = name, password
but in this case even if name
or password
are None
, user
still gets instantiated (empty but still exists, so the if user:
test is true).
How to would I not instantiate an object based on specific arguments?
Upvotes: 29
Views: 30585
Reputation: 749
Something like this :
class User():
def __init__(self, name, password):
self._name = self._password = None
self.name = name
self.password = password
@property
def name(self):
return self._name
@name.setter
def name(self, name: str) -> None:
if not name:
raise TypeError("name is required")
if len(name) < 5: # exemple
raise ValueError("name must have 5 characters or more")
self._name = name
# Do the same for password
Then do something like this in your code, or put it in a class method as Factory pattern and return it.
try:
user = User(name, password)
except (TypeError, ValueError):
user = None
Upvotes: 1
Reputation: 1124070
You'll have to use a __new__
method; by the time __init__
is called a new instance has already been created.
class User(object):
def __new__(cls, name, password):
if name and password:
instance = super(User, cls).__new__(cls)
instance.name, instance.password = name, password
return instance
However, you are violating expectations; when you call a class, I'd expect to always get a new instance. Either raise an exception, or use a classmethod instead.
Raising an exception:
class User(object):
def __init__(self, name, password):
if not (name and password):
raise ValueError('Empty name or password not allowed')
self.name, self.password = name, password
try:
user = User(name, password)
except ValueError:
# oops, no username or password
else:
# ...do stuff
or using a classmethod:
class User(object):
def __init__(self, name, password):
self.name, self.password = name, password
@classmethod
def create_valid_user(cls, name, password):
"""Create a user, or return None if conditions are not met"""
if not (name and password):
return None
return cls(name, password)
user = User.create_valid_user(name, password)
if user is not None:
# ...do stuff
Upvotes: 50
Reputation: 499
It's wrong way. You shold add a method in your User class named check(). Or(better way), create a static method createUser(name, password). It looks like:
user = User.createUser(name, password)
Upvotes: 1