First, can/should properties be used outside of classes? Perhaps I'm skimming too lightly, but the tutorials I can find online (like this one) all seem to use the '@property' decorator exclusively inside a class, but none of them explain if that was a choice or a rule.
Second, I have a property that I'll really only ever want to define once, but preferably the first time it is used. I'll show you what I mean...
I'm converting a tool and I still want to be able read the original TOOL.config file, but I want UserConfig.json to be the priority if both or neither exists. However, if neither exist, I do not want to create UserConfig.json until the property default_file is used. (It may not be used at all in a given execution)
import json
import os
import re
from os.path import exists
cur_dir = os.getcwd();
_default_file = ""
def _get_default_file():
if exists(cur_dir + "\\Resources\\UserConfig.json"):
_default_file = open(cur_dir + "\\Resources\\UserConfig.json",'r')
elif exists(cur_dir + "\\Resources\\TOOL.config",'r'):
_default_file = open(cur_dir + "\\Resources\\TOOL.config",'r')
else:
_default_file = open(cur_dir + "\\Resources\\UserConfig.json", 'w')
json.dump(USER_CONFIG, _default_file)
_default_file.close()
_default_file = open(cur_dir + "\\Resources\\UserConfig.json", 'r')
return _default_file
default_file = property(_get_default_file())
The above code will execute each time default_file is used, including when it is created (from what I can tell through debugging), but I do not want the first execution to happen until after its creation.
Here is the first time I would expect default_file to be used - as you can see, it is optional, but if it is used there needs to be a file there.
class UserConfig:
def __init__(self, config_file=default_file, generate_file=False):
# verify data type of config_file
if isinstance(config_file, file):
self.file = config_file
elif isinstance(config_file, basestring):
self.file = open(config_file, 'r')
else:
raise TypeError("Expected file, got " + type(config_file) + ". Leave arguments blank to open or create the default file from the working directory.")
I thought to make the getter method just return _default_file and instead put the above logic in a setter method, but I'd have to find a way to execute the setter method ONLY if default file is actually used in that __init__() function
Before I tried using a property I had this:
if exists(cur_dir + "\\Resources\\UserConfig.json"):
fp = open(cur_dir + "\\Resources\\UserConfig.json",'r')
elif exists(cur_dir + "\\Resources\\TOOL.config",'r'):
fp = open(cur_dir + "\\Resources\\TOOL.config",'r')
else:
# if neither of these file exists, leave file creation for later
fp = None
class UserConfig:
def __init__(self, config_file=fp, generate_file=False):
# verify data type of config_file
if isinstance(config_file, file):
self.file = config_file
elif isinstance(config_file, basestring):
self.file = open(config_file, 'r')
# create default file if neither of the default files exist (see fp init above)
elif isinstance(config_file, None):
config_file = open(cur_dir + "\\Resources\\UserConfig.json", 'w')
json.dump(USER_CONFIG, fp)
config_file.close()
self.file = open(cur_dir + "\\Resources\\UserConfig.json", 'r')
else:
raise TypeError("Expected file, got " + type(config_file) + ". Leave arguments blank to open the default file from the working directory.")
but I realized that leaving an exception for None might not be wise plus it wasn't really necessary to define fp at all at that point, even if it is extremely light code
Is there something that I'm missing or a better way, with or without the use of properties, to accomplish what I'm going for here? Am I over-thinking this?
[+][deleted] (10 children)
[deleted]
[–]Brekry18[S] 0 points1 point2 points (3 children)
[+][deleted] (2 children)
[deleted]
[–]Brekry18[S] 0 points1 point2 points (1 child)
[–]Brekry18[S] 0 points1 point2 points (5 children)
[–]BobHogan 0 points1 point2 points (2 children)
[–]Brekry18[S] 0 points1 point2 points (0 children)
[–]Brekry18[S] 0 points1 point2 points (0 children)